diff --git "a/linux-clang/linux6.8-zen/patches/0000-[PATCH_v2_1_31]_ntsync:_Introduce_the_ntsync_driver_and_character\n_device..patch" "b/linux-clang/linux6.8-zen/patches/0000-[PATCH_v2_1_31]_ntsync:_Introduce_the_ntsync_driver_and_character\n_device..patch" deleted file mode 100644 index 5193a8c..0000000 --- "a/linux-clang/linux6.8-zen/patches/0000-[PATCH_v2_1_31]_ntsync:_Introduce_the_ntsync_driver_and_character\n_device..patch" +++ /dev/null @@ -1,107 +0,0 @@ -ntsync uses a misc device as the simplest and least intrusive uAPI interface. - -Each file description on the device represents an isolated NT instance, intended -to correspond to a single NT virtual machine. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/Kconfig | 11 +++++++++ - drivers/misc/Makefile | 1 + - drivers/misc/ntsync.c | 52 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 64 insertions(+) - create mode 100644 drivers/misc/ntsync.c - -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index 4fb291f0bf7c..801ed229ed7d 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -506,6 +506,17 @@ config OPEN_DICE - - If unsure, say N. - -+config NTSYNC -+ tristate "NT synchronization primitive emulation" -+ help -+ This module provides kernel support for emulation of Windows NT -+ synchronization primitives. It is not a hardware driver. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called ntsync. -+ -+ If unsure, say N. -+ - config VCPU_STALL_DETECTOR - tristate "Guest vCPU stall detector" - depends on OF && HAS_IOMEM -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index ea6ea5bbbc9c..153a3f4837e8 100644 ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -59,6 +59,7 @@ obj-$(CONFIG_PVPANIC) += pvpanic/ - obj-$(CONFIG_UACCE) += uacce/ - obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o - obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o -+obj-$(CONFIG_NTSYNC) += ntsync.o - obj-$(CONFIG_HI6421V600_IRQ) += hi6421v600-irq.o - obj-$(CONFIG_OPEN_DICE) += open-dice.o - obj-$(CONFIG_GP_PCI1XXXX) += mchp_pci1xxxx/ -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -new file mode 100644 -index 000000000000..bd76e653d83e ---- /dev/null -+++ b/drivers/misc/ntsync.c -@@ -0,0 +1,52 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * ntsync.c - Kernel driver for NT synchronization primitives -+ * -+ * Copyright (C) 2024 Elizabeth Figura -+ */ -+ -+#include -+#include -+#include -+ -+#define NTSYNC_NAME "ntsync" -+ -+static int ntsync_char_open(struct inode *inode, struct file *file) -+{ -+ return nonseekable_open(inode, file); -+} -+ -+static int ntsync_char_release(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+static long ntsync_char_ioctl(struct file *file, unsigned int cmd, -+ unsigned long parm) -+{ -+ switch (cmd) { -+ default: -+ return -ENOIOCTLCMD; -+ } -+} -+ -+static const struct file_operations ntsync_fops = { -+ .owner = THIS_MODULE, -+ .open = ntsync_char_open, -+ .release = ntsync_char_release, -+ .unlocked_ioctl = ntsync_char_ioctl, -+ .compat_ioctl = compat_ptr_ioctl, -+ .llseek = no_llseek, -+}; -+ -+static struct miscdevice ntsync_misc = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = NTSYNC_NAME, -+ .fops = &ntsync_fops, -+}; -+ -+module_misc_device(ntsync_misc); -+ -+MODULE_AUTHOR("Elizabeth Figura "); -+MODULE_DESCRIPTION("Kernel driver for NT synchronization primitives"); -+MODULE_LICENSE("GPL"); --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0001-[PATCH_v2_2_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_SEM..patch b/linux-clang/linux6.8-zen/patches/0001-[PATCH_v2_2_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_SEM..patch deleted file mode 100644 index 6d223a2..0000000 --- a/linux-clang/linux6.8-zen/patches/0001-[PATCH_v2_2_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_SEM..patch +++ /dev/null @@ -1,228 +0,0 @@ -This corresponds to the NT syscall NtCreateSemaphore(). - -Semaphores are one of three types of object to be implemented in this driver, -the others being mutexes and events. - -An NT semaphore contains a 32-bit counter, and is signaled and can be acquired -when the counter is nonzero. The counter has a maximum value which is specified -at creation time. The initial value of the semaphore is also specified at -creation time. There are no restrictions on the maximum and initial value. - -Each object is exposed as an file, to which any number of fds may be opened. -When all fds are closed, the object is deleted. - -Objects hold a pointer to the ntsync_device that created them. The device's -reference count is driven by struct file. - -Signed-off-by: Elizabeth Figura ---- - .../userspace-api/ioctl/ioctl-number.rst | 2 + - drivers/misc/ntsync.c | 131 ++++++++++++++++++ - include/uapi/linux/ntsync.h | 21 +++ - 3 files changed, 154 insertions(+) - create mode 100644 include/uapi/linux/ntsync.h - -diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst -index 457e16f06e04..2f5c6994f042 100644 ---- a/Documentation/userspace-api/ioctl/ioctl-number.rst -+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst -@@ -173,6 +173,8 @@ Code Seq# Include File Comments - 'M' 00-0F drivers/video/fsl-diu-fb.h conflict! - 'N' 00-1F drivers/usb/scanner.h - 'N' 40-7F drivers/block/nvme.c -+'N' 80-8F uapi/linux/ntsync.h NT synchronization primitives -+ - 'O' 00-06 mtd/ubi-user.h UBI - 'P' all linux/soundcard.h conflict! - 'P' 60-6F sound/sscape_ioctl.h conflict! -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index bd76e653d83e..20158ec148bc 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -5,26 +5,157 @@ - * Copyright (C) 2024 Elizabeth Figura - */ - -+#include -+#include - #include - #include - #include -+#include -+#include - - #define NTSYNC_NAME "ntsync" - -+enum ntsync_type { -+ NTSYNC_TYPE_SEM, -+}; -+ -+/* -+ * Individual synchronization primitives are represented by -+ * struct ntsync_obj, and each primitive is backed by a file. -+ * -+ * The whole namespace is represented by a struct ntsync_device also -+ * backed by a file. -+ * -+ * Both rely on struct file for reference counting. Individual -+ * ntsync_obj objects take a reference to the device when created. -+ */ -+ -+struct ntsync_obj { -+ enum ntsync_type type; -+ -+ union { -+ struct { -+ __u32 count; -+ __u32 max; -+ } sem; -+ } u; -+ -+ struct file *file; -+ struct ntsync_device *dev; -+}; -+ -+struct ntsync_device { -+ struct file *file; -+}; -+ -+static int ntsync_obj_release(struct inode *inode, struct file *file) -+{ -+ struct ntsync_obj *obj = file->private_data; -+ -+ fput(obj->dev->file); -+ kfree(obj); -+ -+ return 0; -+} -+ -+static const struct file_operations ntsync_obj_fops = { -+ .owner = THIS_MODULE, -+ .release = ntsync_obj_release, -+ .llseek = no_llseek, -+}; -+ -+static struct ntsync_obj *ntsync_alloc_obj(struct ntsync_device *dev, -+ enum ntsync_type type) -+{ -+ struct ntsync_obj *obj; -+ -+ obj = kzalloc(sizeof(*obj), GFP_KERNEL); -+ if (!obj) -+ return NULL; -+ obj->type = type; -+ obj->dev = dev; -+ get_file(dev->file); -+ -+ return obj; -+} -+ -+static int ntsync_obj_get_fd(struct ntsync_obj *obj) -+{ -+ struct file *file; -+ int fd; -+ -+ fd = get_unused_fd_flags(O_CLOEXEC); -+ if (fd < 0) -+ return fd; -+ file = anon_inode_getfile("ntsync", &ntsync_obj_fops, obj, O_RDWR); -+ if (IS_ERR(file)) { -+ put_unused_fd(fd); -+ return PTR_ERR(file); -+ } -+ obj->file = file; -+ fd_install(fd, file); -+ -+ return fd; -+} -+ -+static int ntsync_create_sem(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_sem_args __user *user_args = argp; -+ struct ntsync_sem_args args; -+ struct ntsync_obj *sem; -+ int fd; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ if (args.count > args.max) -+ return -EINVAL; -+ -+ sem = ntsync_alloc_obj(dev, NTSYNC_TYPE_SEM); -+ if (!sem) -+ return -ENOMEM; -+ sem->u.sem.count = args.count; -+ sem->u.sem.max = args.max; -+ fd = ntsync_obj_get_fd(sem); -+ if (fd < 0) { -+ kfree(sem); -+ return fd; -+ } -+ -+ return put_user(fd, &user_args->sem); -+} -+ - static int ntsync_char_open(struct inode *inode, struct file *file) - { -+ struct ntsync_device *dev; -+ -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); -+ if (!dev) -+ return -ENOMEM; -+ -+ file->private_data = dev; -+ dev->file = file; - return nonseekable_open(inode, file); - } - - static int ntsync_char_release(struct inode *inode, struct file *file) - { -+ struct ntsync_device *dev = file->private_data; -+ -+ kfree(dev); -+ - return 0; - } - - static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - unsigned long parm) - { -+ struct ntsync_device *dev = file->private_data; -+ void __user *argp = (void __user *)parm; -+ - switch (cmd) { -+ case NTSYNC_IOC_CREATE_SEM: -+ return ntsync_create_sem(dev, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -new file mode 100644 -index 000000000000..6a4867a6c97b ---- /dev/null -+++ b/include/uapi/linux/ntsync.h -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * Kernel support for NT synchronization primitive emulation -+ * -+ * Copyright (C) 2021-2022 Elizabeth Figura -+ */ -+ -+#ifndef __LINUX_NTSYNC_H -+#define __LINUX_NTSYNC_H -+ -+#include -+ -+struct ntsync_sem_args { -+ __u32 sem; -+ __u32 count; -+ __u32 max; -+}; -+ -+#define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) -+ -+#endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0002-[PATCH_v2_3_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_POST..patch b/linux-clang/linux6.8-zen/patches/0002-[PATCH_v2_3_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_POST..patch deleted file mode 100644 index 78fdffc..0000000 --- a/linux-clang/linux6.8-zen/patches/0002-[PATCH_v2_3_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_POST..patch +++ /dev/null @@ -1,147 +0,0 @@ -This corresponds to the NT syscall NtReleaseSemaphore(). - -This increases the semaphore's internal counter by the given value, and returns -the previous value. If the counter would overflow the defined maximum, the -function instead fails and returns -EOVERFLOW. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 72 +++++++++++++++++++++++++++++++++++-- - include/uapi/linux/ntsync.h | 2 ++ - 2 files changed, 71 insertions(+), 3 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 20158ec148bc..3c2f743c58b0 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -10,7 +10,9 @@ - #include - #include - #include -+#include - #include -+#include - #include - - #define NTSYNC_NAME "ntsync" -@@ -31,23 +33,70 @@ enum ntsync_type { - */ - - struct ntsync_obj { -+ spinlock_t lock; -+ - enum ntsync_type type; - -+ struct file *file; -+ struct ntsync_device *dev; -+ -+ /* The following fields are protected by the object lock. */ - union { - struct { - __u32 count; - __u32 max; - } sem; - } u; -- -- struct file *file; -- struct ntsync_device *dev; - }; - - struct ntsync_device { - struct file *file; - }; - -+/* -+ * Actually change the semaphore state, returning -EOVERFLOW if it is made -+ * invalid. -+ */ -+static int post_sem_state(struct ntsync_obj *sem, __u32 count) -+{ -+ __u32 sum; -+ -+ lockdep_assert_held(&sem->lock); -+ -+ if (check_add_overflow(sem->u.sem.count, count, &sum) || -+ sum > sem->u.sem.max) -+ return -EOVERFLOW; -+ -+ sem->u.sem.count = sum; -+ return 0; -+} -+ -+static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) -+{ -+ __u32 __user *user_args = argp; -+ __u32 prev_count; -+ __u32 args; -+ int ret; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ if (sem->type != NTSYNC_TYPE_SEM) -+ return -EINVAL; -+ -+ spin_lock(&sem->lock); -+ -+ prev_count = sem->u.sem.count; -+ ret = post_sem_state(sem, args); -+ -+ spin_unlock(&sem->lock); -+ -+ if (!ret && put_user(prev_count, user_args)) -+ ret = -EFAULT; -+ -+ return ret; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -58,9 +107,25 @@ static int ntsync_obj_release(struct inode *inode, struct file *file) - return 0; - } - -+static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, -+ unsigned long parm) -+{ -+ struct ntsync_obj *obj = file->private_data; -+ void __user *argp = (void __user *)parm; -+ -+ switch (cmd) { -+ case NTSYNC_IOC_SEM_POST: -+ return ntsync_sem_post(obj, argp); -+ default: -+ return -ENOIOCTLCMD; -+ } -+} -+ - static const struct file_operations ntsync_obj_fops = { - .owner = THIS_MODULE, - .release = ntsync_obj_release, -+ .unlocked_ioctl = ntsync_obj_ioctl, -+ .compat_ioctl = compat_ptr_ioctl, - .llseek = no_llseek, - }; - -@@ -75,6 +140,7 @@ static struct ntsync_obj *ntsync_alloc_obj(struct ntsync_device *dev, - obj->type = type; - obj->dev = dev; - get_file(dev->file); -+ spin_lock_init(&obj->lock); - - return obj; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 6a4867a6c97b..dcfa38fdc93c 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -18,4 +18,6 @@ struct ntsync_sem_args { - - #define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) - -+#define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) -+ - #endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0003-[PATCH_v2_4_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ANY..patch b/linux-clang/linux6.8-zen/patches/0003-[PATCH_v2_4_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ANY..patch deleted file mode 100644 index 6d57657..0000000 --- a/linux-clang/linux6.8-zen/patches/0003-[PATCH_v2_4_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ANY..patch +++ /dev/null @@ -1,360 +0,0 @@ -This corresponds to part of the functionality of the NT syscall -NtWaitForMultipleObjects(). Specifically, it implements the behaviour where -the third argument (wait_any) is TRUE, and it does not handle alertable waits. -Those features have been split out into separate patches to ease review. - -NTSYNC_IOC_WAIT_ANY is a vectored wait function similar to poll(). Unlike -poll(), it "consumes" objects when they are signaled. For semaphores, this means -decreasing one from the internal counter. At most one object can be consumed by -this function. - -Up to 64 objects can be waited on at once. As soon as one is signaled, the -object with the lowest index is consumed, and that index is returned via the -"index" field. - -A timeout is supported. The timeout is passed as a u64 nanosecond value, which -represents absolute time measured against the MONOTONIC clock. If U64_MAX is -passed, the ioctl waits indefinitely. - -This ioctl validates that all objects belong to the relevant device. This is not -necessary for any technical reason related to NTSYNC_IOC_WAIT_ANY, but will be -necessary for NTSYNC_IOC_WAIT_ALL introduced in the following patch. - -Wait ioctls need to take a temporary reference to each object being waited on. -As with the device, the reference count of struct file is used for ntsync_obj. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 239 ++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 12 ++ - 2 files changed, 251 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 3c2f743c58b0..ad93ca0f8b84 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -6,11 +6,16 @@ - */ - - #include -+#include - #include - #include -+#include -+#include - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -30,6 +35,8 @@ enum ntsync_type { - * - * Both rely on struct file for reference counting. Individual - * ntsync_obj objects take a reference to the device when created. -+ * Wait operations take a reference to each object being waited on for -+ * the duration of the wait. - */ - - struct ntsync_obj { -@@ -47,12 +54,55 @@ struct ntsync_obj { - __u32 max; - } sem; - } u; -+ -+ struct list_head any_waiters; -+}; -+ -+struct ntsync_q_entry { -+ struct list_head node; -+ struct ntsync_q *q; -+ struct ntsync_obj *obj; -+ __u32 index; -+}; -+ -+struct ntsync_q { -+ struct task_struct *task; -+ __u32 owner; -+ -+ /* -+ * Protected via atomic_cmpxchg(). Only the thread that wins the -+ * compare-and-swap may actually change object states and wake this -+ * task. -+ */ -+ atomic_t signaled; -+ -+ __u32 count; -+ struct ntsync_q_entry entries[]; - }; - - struct ntsync_device { - struct file *file; - }; - -+static void try_wake_any_sem(struct ntsync_obj *sem) -+{ -+ struct ntsync_q_entry *entry; -+ -+ lockdep_assert_held(&sem->lock); -+ -+ list_for_each_entry(entry, &sem->any_waiters, node) { -+ struct ntsync_q *q = entry->q; -+ -+ if (!sem->u.sem.count) -+ break; -+ -+ if (atomic_cmpxchg(&q->signaled, -1, entry->index) == -1) { -+ sem->u.sem.count--; -+ wake_up_process(q->task); -+ } -+ } -+} -+ - /* - * Actually change the semaphore state, returning -EOVERFLOW if it is made - * invalid. -@@ -88,6 +138,8 @@ static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) - - prev_count = sem->u.sem.count; - ret = post_sem_state(sem, args); -+ if (!ret) -+ try_wake_any_sem(sem); - - spin_unlock(&sem->lock); - -@@ -141,6 +193,7 @@ static struct ntsync_obj *ntsync_alloc_obj(struct ntsync_device *dev, - obj->dev = dev; - get_file(dev->file); - spin_lock_init(&obj->lock); -+ INIT_LIST_HEAD(&obj->any_waiters); - - return obj; - } -@@ -191,6 +244,190 @@ static int ntsync_create_sem(struct ntsync_device *dev, void __user *argp) - return put_user(fd, &user_args->sem); - } - -+static struct ntsync_obj *get_obj(struct ntsync_device *dev, int fd) -+{ -+ struct file *file = fget(fd); -+ struct ntsync_obj *obj; -+ -+ if (file->f_op != &ntsync_obj_fops) { -+ fput(file); -+ return NULL; -+ } -+ -+ obj = file->private_data; -+ if (obj->dev != dev) { -+ fput(file); -+ return NULL; -+ } -+ -+ return obj; -+} -+ -+static void put_obj(struct ntsync_obj *obj) -+{ -+ fput(obj->file); -+} -+ -+static int ntsync_schedule(const struct ntsync_q *q, const struct ntsync_wait_args *args) -+{ -+ ktime_t timeout = ns_to_ktime(args->timeout); -+ ktime_t *timeout_ptr; -+ int ret = 0; -+ -+ timeout_ptr = (args->timeout == U64_MAX ? NULL : &timeout); -+ -+ do { -+ if (signal_pending(current)) { -+ ret = -ERESTARTSYS; -+ break; -+ } -+ -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (atomic_read(&q->signaled) != -1) { -+ ret = 0; -+ break; -+ } -+ ret = schedule_hrtimeout(timeout_ptr, HRTIMER_MODE_ABS); -+ } while (ret < 0); -+ __set_current_state(TASK_RUNNING); -+ -+ return ret; -+} -+ -+/* -+ * Allocate and initialize the ntsync_q structure, but do not queue us yet. -+ */ -+static int setup_wait(struct ntsync_device *dev, -+ const struct ntsync_wait_args *args, -+ struct ntsync_q **ret_q) -+{ -+ const __u32 count = args->count; -+ int fds[NTSYNC_MAX_WAIT_COUNT]; -+ struct ntsync_q *q; -+ __u32 i, j; -+ -+ if (!args->owner || args->pad) -+ return -EINVAL; -+ -+ if (args->count > NTSYNC_MAX_WAIT_COUNT) -+ return -EINVAL; -+ -+ if (copy_from_user(fds, u64_to_user_ptr(args->objs), -+ array_size(count, sizeof(*fds)))) -+ return -EFAULT; -+ -+ q = kmalloc(struct_size(q, entries, count), GFP_KERNEL); -+ if (!q) -+ return -ENOMEM; -+ q->task = current; -+ q->owner = args->owner; -+ atomic_set(&q->signaled, -1); -+ q->count = count; -+ -+ for (i = 0; i < count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = get_obj(dev, fds[i]); -+ -+ if (!obj) -+ goto err; -+ -+ entry->obj = obj; -+ entry->q = q; -+ entry->index = i; -+ } -+ -+ *ret_q = q; -+ return 0; -+ -+err: -+ for (j = 0; j < i; j++) -+ put_obj(q->entries[j].obj); -+ kfree(q); -+ return -EINVAL; -+} -+ -+static void try_wake_any_obj(struct ntsync_obj *obj) -+{ -+ switch (obj->type) { -+ case NTSYNC_TYPE_SEM: -+ try_wake_any_sem(obj); -+ break; -+ } -+} -+ -+static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_wait_args args; -+ struct ntsync_q *q; -+ int signaled; -+ __u32 i; -+ int ret; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ ret = setup_wait(dev, &args, &q); -+ if (ret < 0) -+ return ret; -+ -+ /* queue ourselves */ -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ spin_lock(&obj->lock); -+ list_add_tail(&entry->node, &obj->any_waiters); -+ spin_unlock(&obj->lock); -+ } -+ -+ /* check if we are already signaled */ -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_obj *obj = q->entries[i].obj; -+ -+ if (atomic_read(&q->signaled) != -1) -+ break; -+ -+ spin_lock(&obj->lock); -+ try_wake_any_obj(obj); -+ spin_unlock(&obj->lock); -+ } -+ -+ /* sleep */ -+ -+ ret = ntsync_schedule(q, &args); -+ -+ /* and finally, unqueue */ -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ spin_lock(&obj->lock); -+ list_del(&entry->node); -+ spin_unlock(&obj->lock); -+ -+ put_obj(obj); -+ } -+ -+ signaled = atomic_read(&q->signaled); -+ if (signaled != -1) { -+ struct ntsync_wait_args __user *user_args = argp; -+ -+ /* even if we caught a signal, we need to communicate success */ -+ ret = 0; -+ -+ if (put_user(signaled, &user_args->index)) -+ ret = -EFAULT; -+ } else if (!ret) { -+ ret = -ETIMEDOUT; -+ } -+ -+ kfree(q); -+ return ret; -+} -+ - static int ntsync_char_open(struct inode *inode, struct file *file) - { - struct ntsync_device *dev; -@@ -222,6 +459,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - switch (cmd) { - case NTSYNC_IOC_CREATE_SEM: - return ntsync_create_sem(dev, argp); -+ case NTSYNC_IOC_WAIT_ANY: -+ return ntsync_wait_any(dev, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index dcfa38fdc93c..56b643fab611 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -16,7 +16,19 @@ struct ntsync_sem_args { - __u32 max; - }; - -+struct ntsync_wait_args { -+ __u64 timeout; -+ __u64 objs; -+ __u32 count; -+ __u32 owner; -+ __u32 index; -+ __u32 pad; -+}; -+ -+#define NTSYNC_MAX_WAIT_COUNT 64 -+ - #define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) -+#define NTSYNC_IOC_WAIT_ANY _IOWR('N', 0x82, struct ntsync_wait_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0004-[PATCH_v2_5_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ALL..patch b/linux-clang/linux6.8-zen/patches/0004-[PATCH_v2_5_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ALL..patch deleted file mode 100644 index 7d2c890..0000000 --- a/linux-clang/linux6.8-zen/patches/0004-[PATCH_v2_5_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ALL..patch +++ /dev/null @@ -1,365 +0,0 @@ -This is similar to NTSYNC_IOC_WAIT_ANY, but waits until all of the objects are -simultaneously signaled, and then acquires all of them as a single atomic -operation. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 242 ++++++++++++++++++++++++++++++++++-- - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 235 insertions(+), 8 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index ad93ca0f8b84..d5759e9a3a8e 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -55,7 +55,34 @@ struct ntsync_obj { - } sem; - } u; - -+ /* -+ * any_waiters is protected by the object lock, but all_waiters is -+ * protected by the device wait_all_lock. -+ */ - struct list_head any_waiters; -+ struct list_head all_waiters; -+ -+ /* -+ * Hint describing how many tasks are queued on this object in a -+ * wait-all operation. -+ * -+ * Any time we do a wake, we may need to wake "all" waiters as well as -+ * "any" waiters. In order to atomically wake "all" waiters, we must -+ * lock all of the objects, and that means grabbing the wait_all_lock -+ * below (and, due to lock ordering rules, before locking this object). -+ * However, wait-all is a rare operation, and grabbing the wait-all -+ * lock for every wake would create unnecessary contention. -+ * Therefore we first check whether all_hint is zero, and, if it is, -+ * we skip trying to wake "all" waiters. -+ * -+ * This hint isn't protected by any lock. It might change during the -+ * course of a wake, but there's no meaningful race there; it's only a -+ * hint. -+ * -+ * Since wait requests must originate from user-space threads, we're -+ * limited here by PID_MAX_LIMIT, so there's no risk of overflow. -+ */ -+ atomic_t all_hint; - }; - - struct ntsync_q_entry { -@@ -76,14 +103,99 @@ struct ntsync_q { - */ - atomic_t signaled; - -+ bool all; - __u32 count; - struct ntsync_q_entry entries[]; - }; - - struct ntsync_device { -+ /* -+ * Wait-all operations must atomically grab all objects, and be totally -+ * ordered with respect to each other and wait-any operations. -+ * If one thread is trying to acquire several objects, another thread -+ * cannot touch the object at the same time. -+ * -+ * We achieve this by grabbing multiple object locks at the same time. -+ * However, this creates a lock ordering problem. To solve that problem, -+ * wait_all_lock is taken first whenever multiple objects must be locked -+ * at the same time. -+ */ -+ spinlock_t wait_all_lock; -+ - struct file *file; - }; - -+static bool is_signaled(struct ntsync_obj *obj, __u32 owner) -+{ -+ lockdep_assert_held(&obj->lock); -+ -+ switch (obj->type) { -+ case NTSYNC_TYPE_SEM: -+ return !!obj->u.sem.count; -+ } -+ -+ WARN(1, "bad object type %#x\n", obj->type); -+ return false; -+} -+ -+/* -+ * "locked_obj" is an optional pointer to an object which is already locked and -+ * should not be locked again. This is necessary so that changing an object's -+ * state and waking it can be a single atomic operation. -+ */ -+static void try_wake_all(struct ntsync_device *dev, struct ntsync_q *q, -+ struct ntsync_obj *locked_obj) -+{ -+ __u32 count = q->count; -+ bool can_wake = true; -+ __u32 i; -+ -+ lockdep_assert_held(&dev->wait_all_lock); -+ if (locked_obj) -+ lockdep_assert_held(&locked_obj->lock); -+ -+ for (i = 0; i < count; i++) { -+ if (q->entries[i].obj != locked_obj) -+ spin_lock_nest_lock(&q->entries[i].obj->lock, &dev->wait_all_lock); -+ } -+ -+ for (i = 0; i < count; i++) { -+ if (!is_signaled(q->entries[i].obj, q->owner)) { -+ can_wake = false; -+ break; -+ } -+ } -+ -+ if (can_wake && atomic_cmpxchg(&q->signaled, -1, 0) == -1) { -+ for (i = 0; i < count; i++) { -+ struct ntsync_obj *obj = q->entries[i].obj; -+ -+ switch (obj->type) { -+ case NTSYNC_TYPE_SEM: -+ obj->u.sem.count--; -+ break; -+ } -+ } -+ wake_up_process(q->task); -+ } -+ -+ for (i = 0; i < count; i++) { -+ if (q->entries[i].obj != locked_obj) -+ spin_unlock(&q->entries[i].obj->lock); -+ } -+} -+ -+static void try_wake_all_obj(struct ntsync_device *dev, struct ntsync_obj *obj) -+{ -+ struct ntsync_q_entry *entry; -+ -+ lockdep_assert_held(&dev->wait_all_lock); -+ lockdep_assert_held(&obj->lock); -+ -+ list_for_each_entry(entry, &obj->all_waiters, node) -+ try_wake_all(dev, entry->q, obj); -+} -+ - static void try_wake_any_sem(struct ntsync_obj *sem) - { - struct ntsync_q_entry *entry; -@@ -123,6 +235,7 @@ static int post_sem_state(struct ntsync_obj *sem, __u32 count) - - static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) - { -+ struct ntsync_device *dev = sem->dev; - __u32 __user *user_args = argp; - __u32 prev_count; - __u32 args; -@@ -134,14 +247,29 @@ static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) - if (sem->type != NTSYNC_TYPE_SEM) - return -EINVAL; - -- spin_lock(&sem->lock); -+ if (atomic_read(&sem->all_hint) > 0) { -+ spin_lock(&dev->wait_all_lock); -+ spin_lock_nest_lock(&sem->lock, &dev->wait_all_lock); - -- prev_count = sem->u.sem.count; -- ret = post_sem_state(sem, args); -- if (!ret) -- try_wake_any_sem(sem); -+ prev_count = sem->u.sem.count; -+ ret = post_sem_state(sem, args); -+ if (!ret) { -+ try_wake_all_obj(dev, sem); -+ try_wake_any_sem(sem); -+ } - -- spin_unlock(&sem->lock); -+ spin_unlock(&sem->lock); -+ spin_unlock(&dev->wait_all_lock); -+ } else { -+ spin_lock(&sem->lock); -+ -+ prev_count = sem->u.sem.count; -+ ret = post_sem_state(sem, args); -+ if (!ret) -+ try_wake_any_sem(sem); -+ -+ spin_unlock(&sem->lock); -+ } - - if (!ret && put_user(prev_count, user_args)) - ret = -EFAULT; -@@ -194,6 +322,8 @@ static struct ntsync_obj *ntsync_alloc_obj(struct ntsync_device *dev, - get_file(dev->file); - spin_lock_init(&obj->lock); - INIT_LIST_HEAD(&obj->any_waiters); -+ INIT_LIST_HEAD(&obj->all_waiters); -+ atomic_set(&obj->all_hint, 0); - - return obj; - } -@@ -298,7 +428,7 @@ static int ntsync_schedule(const struct ntsync_q *q, const struct ntsync_wait_ar - * Allocate and initialize the ntsync_q structure, but do not queue us yet. - */ - static int setup_wait(struct ntsync_device *dev, -- const struct ntsync_wait_args *args, -+ const struct ntsync_wait_args *args, bool all, - struct ntsync_q **ret_q) - { - const __u32 count = args->count; -@@ -322,6 +452,7 @@ static int setup_wait(struct ntsync_device *dev, - q->task = current; - q->owner = args->owner; - atomic_set(&q->signaled, -1); -+ q->all = all; - q->count = count; - - for (i = 0; i < count; i++) { -@@ -331,6 +462,16 @@ static int setup_wait(struct ntsync_device *dev, - if (!obj) - goto err; - -+ if (all) { -+ /* Check that the objects are all distinct. */ -+ for (j = 0; j < i; j++) { -+ if (obj == q->entries[j].obj) { -+ put_obj(obj); -+ goto err; -+ } -+ } -+ } -+ - entry->obj = obj; - entry->q = q; - entry->index = i; -@@ -366,7 +507,7 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - if (copy_from_user(&args, argp, sizeof(args))) - return -EFAULT; - -- ret = setup_wait(dev, &args, &q); -+ ret = setup_wait(dev, &args, false, &q); - if (ret < 0) - return ret; - -@@ -428,6 +569,87 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - return ret; - } - -+static int ntsync_wait_all(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_wait_args args; -+ struct ntsync_q *q; -+ int signaled; -+ __u32 i; -+ int ret; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ ret = setup_wait(dev, &args, true, &q); -+ if (ret < 0) -+ return ret; -+ -+ /* queue ourselves */ -+ -+ spin_lock(&dev->wait_all_lock); -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ atomic_inc(&obj->all_hint); -+ -+ /* -+ * obj->all_waiters is protected by dev->wait_all_lock rather -+ * than obj->lock, so there is no need to acquire obj->lock -+ * here. -+ */ -+ list_add_tail(&entry->node, &obj->all_waiters); -+ } -+ -+ /* check if we are already signaled */ -+ -+ try_wake_all(dev, q, NULL); -+ -+ spin_unlock(&dev->wait_all_lock); -+ -+ /* sleep */ -+ -+ ret = ntsync_schedule(q, &args); -+ -+ /* and finally, unqueue */ -+ -+ spin_lock(&dev->wait_all_lock); -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ /* -+ * obj->all_waiters is protected by dev->wait_all_lock rather -+ * than obj->lock, so there is no need to acquire it here. -+ */ -+ list_del(&entry->node); -+ -+ atomic_dec(&obj->all_hint); -+ -+ put_obj(obj); -+ } -+ -+ spin_unlock(&dev->wait_all_lock); -+ -+ signaled = atomic_read(&q->signaled); -+ if (signaled != -1) { -+ struct ntsync_wait_args __user *user_args = argp; -+ -+ /* even if we caught a signal, we need to communicate success */ -+ ret = 0; -+ -+ if (put_user(signaled, &user_args->index)) -+ ret = -EFAULT; -+ } else if (!ret) { -+ ret = -ETIMEDOUT; -+ } -+ -+ kfree(q); -+ return ret; -+} -+ - static int ntsync_char_open(struct inode *inode, struct file *file) - { - struct ntsync_device *dev; -@@ -436,6 +658,8 @@ static int ntsync_char_open(struct inode *inode, struct file *file) - if (!dev) - return -ENOMEM; - -+ spin_lock_init(&dev->wait_all_lock); -+ - file->private_data = dev; - dev->file = file; - return nonseekable_open(inode, file); -@@ -459,6 +683,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - switch (cmd) { - case NTSYNC_IOC_CREATE_SEM: - return ntsync_create_sem(dev, argp); -+ case NTSYNC_IOC_WAIT_ALL: -+ return ntsync_wait_all(dev, argp); - case NTSYNC_IOC_WAIT_ANY: - return ntsync_wait_any(dev, argp); - default: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 56b643fab611..19c37e27a4f8 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -29,6 +29,7 @@ struct ntsync_wait_args { - - #define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) - #define NTSYNC_IOC_WAIT_ANY _IOWR('N', 0x82, struct ntsync_wait_args) -+#define NTSYNC_IOC_WAIT_ALL _IOWR('N', 0x83, struct ntsync_wait_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0005-[PATCH_v2_6_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_MUTEX..patch b/linux-clang/linux6.8-zen/patches/0005-[PATCH_v2_6_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_MUTEX..patch deleted file mode 100644 index cfd07ce..0000000 --- a/linux-clang/linux6.8-zen/patches/0005-[PATCH_v2_6_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_MUTEX..patch +++ /dev/null @@ -1,172 +0,0 @@ -This corresponds to the NT syscall NtCreateMutant(). - -An NT mutex is recursive, with a 32-bit recursion counter. When acquired via -NtWaitForMultipleObjects(), the recursion counter is incremented by one. - -The OS records the thread which acquired it. However, in order to keep this -driver self-contained, the owning thread ID is managed by user-space, and passed -as a parameter to all relevant ioctls. - -The initial owner and recursion count, if any, are specified when the mutex is -created. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 67 +++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 7 ++++ - 2 files changed, 74 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index d5759e9a3a8e..6f7086d0440a 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -24,6 +24,7 @@ - - enum ntsync_type { - NTSYNC_TYPE_SEM, -+ NTSYNC_TYPE_MUTEX, - }; - - /* -@@ -53,6 +54,10 @@ struct ntsync_obj { - __u32 count; - __u32 max; - } sem; -+ struct { -+ __u32 count; -+ __u32 owner; -+ } mutex; - } u; - - /* -@@ -132,6 +137,10 @@ static bool is_signaled(struct ntsync_obj *obj, __u32 owner) - switch (obj->type) { - case NTSYNC_TYPE_SEM: - return !!obj->u.sem.count; -+ case NTSYNC_TYPE_MUTEX: -+ if (obj->u.mutex.owner && obj->u.mutex.owner != owner) -+ return false; -+ return obj->u.mutex.count < UINT_MAX; - } - - WARN(1, "bad object type %#x\n", obj->type); -@@ -174,6 +183,10 @@ static void try_wake_all(struct ntsync_device *dev, struct ntsync_q *q, - case NTSYNC_TYPE_SEM: - obj->u.sem.count--; - break; -+ case NTSYNC_TYPE_MUTEX: -+ obj->u.mutex.count++; -+ obj->u.mutex.owner = q->owner; -+ break; - } - } - wake_up_process(q->task); -@@ -215,6 +228,28 @@ static void try_wake_any_sem(struct ntsync_obj *sem) - } - } - -+static void try_wake_any_mutex(struct ntsync_obj *mutex) -+{ -+ struct ntsync_q_entry *entry; -+ -+ lockdep_assert_held(&mutex->lock); -+ -+ list_for_each_entry(entry, &mutex->any_waiters, node) { -+ struct ntsync_q *q = entry->q; -+ -+ if (mutex->u.mutex.count == UINT_MAX) -+ break; -+ if (mutex->u.mutex.owner && mutex->u.mutex.owner != q->owner) -+ continue; -+ -+ if (atomic_cmpxchg(&q->signaled, -1, entry->index) == -1) { -+ mutex->u.mutex.count++; -+ mutex->u.mutex.owner = q->owner; -+ wake_up_process(q->task); -+ } -+ } -+} -+ - /* - * Actually change the semaphore state, returning -EOVERFLOW if it is made - * invalid. -@@ -374,6 +409,33 @@ static int ntsync_create_sem(struct ntsync_device *dev, void __user *argp) - return put_user(fd, &user_args->sem); - } - -+static int ntsync_create_mutex(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_mutex_args __user *user_args = argp; -+ struct ntsync_mutex_args args; -+ struct ntsync_obj *mutex; -+ int fd; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ if (!args.owner != !args.count) -+ return -EINVAL; -+ -+ mutex = ntsync_alloc_obj(dev, NTSYNC_TYPE_MUTEX); -+ if (!mutex) -+ return -ENOMEM; -+ mutex->u.mutex.count = args.count; -+ mutex->u.mutex.owner = args.owner; -+ fd = ntsync_obj_get_fd(mutex); -+ if (fd < 0) { -+ kfree(mutex); -+ return fd; -+ } -+ -+ return put_user(fd, &user_args->mutex); -+} -+ - static struct ntsync_obj *get_obj(struct ntsync_device *dev, int fd) - { - struct file *file = fget(fd); -@@ -493,6 +555,9 @@ static void try_wake_any_obj(struct ntsync_obj *obj) - case NTSYNC_TYPE_SEM: - try_wake_any_sem(obj); - break; -+ case NTSYNC_TYPE_MUTEX: -+ try_wake_any_mutex(obj); -+ break; - } - } - -@@ -681,6 +746,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - void __user *argp = (void __user *)parm; - - switch (cmd) { -+ case NTSYNC_IOC_CREATE_MUTEX: -+ return ntsync_create_mutex(dev, argp); - case NTSYNC_IOC_CREATE_SEM: - return ntsync_create_sem(dev, argp); - case NTSYNC_IOC_WAIT_ALL: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 19c37e27a4f8..8ac9d419c360 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -16,6 +16,12 @@ struct ntsync_sem_args { - __u32 max; - }; - -+struct ntsync_mutex_args { -+ __u32 mutex; -+ __u32 owner; -+ __u32 count; -+}; -+ - struct ntsync_wait_args { - __u64 timeout; - __u64 objs; -@@ -30,6 +36,7 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) - #define NTSYNC_IOC_WAIT_ANY _IOWR('N', 0x82, struct ntsync_wait_args) - #define NTSYNC_IOC_WAIT_ALL _IOWR('N', 0x83, struct ntsync_wait_args) -+#define NTSYNC_IOC_CREATE_MUTEX _IOWR('N', 0x84, struct ntsync_sem_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0006-[PATCH_v2_7_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_UNLOCK..patch b/linux-clang/linux6.8-zen/patches/0006-[PATCH_v2_7_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_UNLOCK..patch deleted file mode 100644 index 97e5ace..0000000 --- a/linux-clang/linux6.8-zen/patches/0006-[PATCH_v2_7_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_UNLOCK..patch +++ /dev/null @@ -1,107 +0,0 @@ -This corresponds to the NT syscall NtReleaseMutant(). - -This syscall decrements the mutex's recursion count by one, and returns the -previous value. If the mutex is not owned by the given owner ID, the function -instead fails and returns -EPERM. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 64 +++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 65 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 6f7086d0440a..222ebead8eba 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -312,6 +312,68 @@ static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) - return ret; - } - -+/* -+ * Actually change the mutex state, returning -EPERM if not the owner. -+ */ -+static int unlock_mutex_state(struct ntsync_obj *mutex, -+ const struct ntsync_mutex_args *args) -+{ -+ lockdep_assert_held(&mutex->lock); -+ -+ if (mutex->u.mutex.owner != args->owner) -+ return -EPERM; -+ -+ if (!--mutex->u.mutex.count) -+ mutex->u.mutex.owner = 0; -+ return 0; -+} -+ -+static int ntsync_mutex_unlock(struct ntsync_obj *mutex, void __user *argp) -+{ -+ struct ntsync_mutex_args __user *user_args = argp; -+ struct ntsync_device *dev = mutex->dev; -+ struct ntsync_mutex_args args; -+ __u32 prev_count; -+ int ret; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ if (!args.owner) -+ return -EINVAL; -+ -+ if (mutex->type != NTSYNC_TYPE_MUTEX) -+ return -EINVAL; -+ -+ if (atomic_read(&mutex->all_hint) > 0) { -+ spin_lock(&dev->wait_all_lock); -+ spin_lock_nest_lock(&mutex->lock, &dev->wait_all_lock); -+ -+ prev_count = mutex->u.mutex.count; -+ ret = unlock_mutex_state(mutex, &args); -+ if (!ret) { -+ try_wake_all_obj(dev, mutex); -+ try_wake_any_mutex(mutex); -+ } -+ -+ spin_unlock(&mutex->lock); -+ spin_unlock(&dev->wait_all_lock); -+ } else { -+ spin_lock(&mutex->lock); -+ -+ prev_count = mutex->u.mutex.count; -+ ret = unlock_mutex_state(mutex, &args); -+ if (!ret) -+ try_wake_any_mutex(mutex); -+ -+ spin_unlock(&mutex->lock); -+ } -+ -+ if (!ret && put_user(prev_count, &user_args->count)) -+ ret = -EFAULT; -+ -+ return ret; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -331,6 +393,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - switch (cmd) { - case NTSYNC_IOC_SEM_POST: - return ntsync_sem_post(obj, argp); -+ case NTSYNC_IOC_MUTEX_UNLOCK: -+ return ntsync_mutex_unlock(obj, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 8ac9d419c360..265503d441b1 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -39,5 +39,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_CREATE_MUTEX _IOWR('N', 0x84, struct ntsync_sem_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) -+#define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) - - #endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0007-[PATCH_v2_8_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_KILL..patch b/linux-clang/linux6.8-zen/patches/0007-[PATCH_v2_8_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_KILL..patch deleted file mode 100644 index ec55ac0..0000000 --- a/linux-clang/linux6.8-zen/patches/0007-[PATCH_v2_8_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_KILL..patch +++ /dev/null @@ -1,166 +0,0 @@ -This does not correspond to any NT syscall. Rather, when a thread dies, it -should be called by the NT emulator for each mutex. - -NT mutexes are robust (in the pthread sense). When an NT thread dies, any -mutexes it owned are immediately released. Acquisition of those mutexes by other -threads will return a special value indicating that the mutex was abandoned, -like EOWNERDEAD returned from pthread_mutex_lock(), and EOWNERDEAD is indeed -used here for that purpose. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 71 +++++++++++++++++++++++++++++++++++-- - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 70 insertions(+), 2 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 222ebead8eba..a3466be50c45 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -57,6 +57,7 @@ struct ntsync_obj { - struct { - __u32 count; - __u32 owner; -+ bool ownerdead; - } mutex; - } u; - -@@ -109,6 +110,7 @@ struct ntsync_q { - atomic_t signaled; - - bool all; -+ bool ownerdead; - __u32 count; - struct ntsync_q_entry entries[]; - }; -@@ -184,6 +186,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; -@@ -243,6 +248,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); -@@ -374,6 +382,62 @@ static int ntsync_mutex_unlock(struct ntsync_obj *mutex, void __user *argp) - return ret; - } - -+/* -+ * Actually change the mutex state to mark its owner as dead, -+ * returning -EPERM if not the owner. -+ */ -+static int kill_mutex_state(struct ntsync_obj *mutex, __u32 owner) -+{ -+ lockdep_assert_held(&mutex->lock); -+ -+ if (mutex->u.mutex.owner != owner) -+ return -EPERM; -+ -+ mutex->u.mutex.ownerdead = true; -+ mutex->u.mutex.owner = 0; -+ mutex->u.mutex.count = 0; -+ return 0; -+} -+ -+static int ntsync_mutex_kill(struct ntsync_obj *mutex, void __user *argp) -+{ -+ struct ntsync_device *dev = mutex->dev; -+ __u32 owner; -+ int ret; -+ -+ if (get_user(owner, (__u32 __user *)argp)) -+ return -EFAULT; -+ if (!owner) -+ return -EINVAL; -+ -+ if (mutex->type != NTSYNC_TYPE_MUTEX) -+ return -EINVAL; -+ -+ if (atomic_read(&mutex->all_hint) > 0) { -+ spin_lock(&dev->wait_all_lock); -+ spin_lock_nest_lock(&mutex->lock, &dev->wait_all_lock); -+ -+ ret = kill_mutex_state(mutex, owner); -+ if (!ret) { -+ try_wake_all_obj(dev, mutex); -+ try_wake_any_mutex(mutex); -+ } -+ -+ spin_unlock(&mutex->lock); -+ spin_unlock(&dev->wait_all_lock); -+ } else { -+ spin_lock(&mutex->lock); -+ -+ ret = kill_mutex_state(mutex, owner); -+ if (!ret) -+ try_wake_any_mutex(mutex); -+ -+ spin_unlock(&mutex->lock); -+ } -+ -+ return ret; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -395,6 +459,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_sem_post(obj, argp); - case NTSYNC_IOC_MUTEX_UNLOCK: - return ntsync_mutex_unlock(obj, argp); -+ case NTSYNC_IOC_MUTEX_KILL: -+ return ntsync_mutex_kill(obj, argp); - default: - return -ENOIOCTLCMD; - } -@@ -579,6 +645,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++) { -@@ -686,7 +753,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; -@@ -767,7 +834,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; -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 265503d441b1..4800941fcbda 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -40,5 +40,6 @@ struct ntsync_wait_args { - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - #define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) -+#define NTSYNC_IOC_MUTEX_KILL _IOW ('N', 0x86, __u32) - - #endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0008-[PATCH_v2_9_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_EVENT..patch b/linux-clang/linux6.8-zen/patches/0008-[PATCH_v2_9_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_EVENT..patch deleted file mode 100644 index 7376a14..0000000 --- a/linux-clang/linux6.8-zen/patches/0008-[PATCH_v2_9_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_EVENT..patch +++ /dev/null @@ -1,165 +0,0 @@ -This correspond to the NT syscall NtCreateEvent(). - -An NT event holds a single bit of state denoting whether it is signaled or -unsignaled. - -There are two types of events: manual-reset and automatic-reset. When an -automatic-reset event is acquired via a wait function, its state is reset to -unsignaled. Manual-reset events are not affected by wait functions. - -Whether the event is manual-reset, and its initial state, are specified at -creation time. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 60 +++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 7 +++++ - 2 files changed, 67 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index a3466be50c45..17dd47d06e0a 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -25,6 +25,7 @@ - enum ntsync_type { - NTSYNC_TYPE_SEM, - NTSYNC_TYPE_MUTEX, -+ NTSYNC_TYPE_EVENT, - }; - - /* -@@ -59,6 +60,10 @@ struct ntsync_obj { - __u32 owner; - bool ownerdead; - } mutex; -+ struct { -+ bool manual; -+ bool signaled; -+ } event; - } u; - - /* -@@ -143,6 +148,8 @@ static bool is_signaled(struct ntsync_obj *obj, __u32 owner) - if (obj->u.mutex.owner && obj->u.mutex.owner != owner) - return false; - return obj->u.mutex.count < UINT_MAX; -+ case NTSYNC_TYPE_EVENT: -+ return obj->u.event.signaled; - } - - WARN(1, "bad object type %#x\n", obj->type); -@@ -192,6 +199,10 @@ static void try_wake_all(struct ntsync_device *dev, struct ntsync_q *q, - obj->u.mutex.count++; - obj->u.mutex.owner = q->owner; - break; -+ case NTSYNC_TYPE_EVENT: -+ if (!obj->u.event.manual) -+ obj->u.event.signaled = false; -+ break; - } - } - wake_up_process(q->task); -@@ -258,6 +269,26 @@ static void try_wake_any_mutex(struct ntsync_obj *mutex) - } - } - -+static void try_wake_any_event(struct ntsync_obj *event) -+{ -+ struct ntsync_q_entry *entry; -+ -+ lockdep_assert_held(&event->lock); -+ -+ list_for_each_entry(entry, &event->any_waiters, node) { -+ struct ntsync_q *q = entry->q; -+ -+ if (!event->u.event.signaled) -+ break; -+ -+ if (atomic_cmpxchg(&q->signaled, -1, entry->index) == -1) { -+ if (!event->u.event.manual) -+ event->u.event.signaled = false; -+ wake_up_process(q->task); -+ } -+ } -+} -+ - /* - * Actually change the semaphore state, returning -EOVERFLOW if it is made - * invalid. -@@ -566,6 +597,30 @@ static int ntsync_create_mutex(struct ntsync_device *dev, void __user *argp) - return put_user(fd, &user_args->mutex); - } - -+static int ntsync_create_event(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_event_args __user *user_args = argp; -+ struct ntsync_event_args args; -+ struct ntsync_obj *event; -+ int fd; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ event = ntsync_alloc_obj(dev, NTSYNC_TYPE_EVENT); -+ if (!event) -+ return -ENOMEM; -+ event->u.event.manual = args.manual; -+ event->u.event.signaled = args.signaled; -+ fd = ntsync_obj_get_fd(event); -+ if (fd < 0) { -+ kfree(event); -+ return fd; -+ } -+ -+ return put_user(fd, &user_args->event); -+} -+ - static struct ntsync_obj *get_obj(struct ntsync_device *dev, int fd) - { - struct file *file = fget(fd); -@@ -689,6 +744,9 @@ static void try_wake_any_obj(struct ntsync_obj *obj) - case NTSYNC_TYPE_MUTEX: - try_wake_any_mutex(obj); - break; -+ case NTSYNC_TYPE_EVENT: -+ try_wake_any_event(obj); -+ break; - } - } - -@@ -877,6 +935,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - void __user *argp = (void __user *)parm; - - switch (cmd) { -+ case NTSYNC_IOC_CREATE_EVENT: -+ return ntsync_create_event(dev, argp); - case NTSYNC_IOC_CREATE_MUTEX: - return ntsync_create_mutex(dev, argp); - case NTSYNC_IOC_CREATE_SEM: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 4800941fcbda..040cbdb39033 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -22,6 +22,12 @@ struct ntsync_mutex_args { - __u32 count; - }; - -+struct ntsync_event_args { -+ __u32 event; -+ __u32 manual; -+ __u32 signaled; -+}; -+ - struct ntsync_wait_args { - __u64 timeout; - __u64 objs; -@@ -37,6 +43,7 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_WAIT_ANY _IOWR('N', 0x82, struct ntsync_wait_args) - #define NTSYNC_IOC_WAIT_ALL _IOWR('N', 0x83, struct ntsync_wait_args) - #define NTSYNC_IOC_CREATE_MUTEX _IOWR('N', 0x84, struct ntsync_sem_args) -+#define NTSYNC_IOC_CREATE_EVENT _IOWR('N', 0x87, struct ntsync_event_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - #define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0009-[PATCH_v2_10_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_SET..patch b/linux-clang/linux6.8-zen/patches/0009-[PATCH_v2_10_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_SET..patch deleted file mode 100644 index 58e9472..0000000 --- a/linux-clang/linux6.8-zen/patches/0009-[PATCH_v2_10_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_SET..patch +++ /dev/null @@ -1,78 +0,0 @@ -This corresponds to the NT syscall NtSetEvent(). - -This sets the event to the signaled state, and returns its previous state. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 37 +++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 38 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 17dd47d06e0a..edfbf11cafe0 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -469,6 +469,41 @@ static int ntsync_mutex_kill(struct ntsync_obj *mutex, void __user *argp) - return ret; - } - -+static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) -+{ -+ struct ntsync_device *dev = event->dev; -+ __u32 prev_state; -+ -+ if (event->type != NTSYNC_TYPE_EVENT) -+ return -EINVAL; -+ -+ if (atomic_read(&event->all_hint) > 0) { -+ spin_lock(&dev->wait_all_lock); -+ spin_lock_nest_lock(&event->lock, &dev->wait_all_lock); -+ -+ prev_state = event->u.event.signaled; -+ event->u.event.signaled = true; -+ try_wake_all_obj(dev, event); -+ try_wake_any_event(event); -+ -+ spin_unlock(&event->lock); -+ spin_unlock(&dev->wait_all_lock); -+ } else { -+ spin_lock(&event->lock); -+ -+ prev_state = event->u.event.signaled; -+ event->u.event.signaled = true; -+ try_wake_any_event(event); -+ -+ spin_unlock(&event->lock); -+ } -+ -+ if (put_user(prev_state, (__u32 __user *)argp)) -+ return -EFAULT; -+ -+ return 0; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -492,6 +527,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_mutex_unlock(obj, argp); - case NTSYNC_IOC_MUTEX_KILL: - return ntsync_mutex_kill(obj, argp); -+ case NTSYNC_IOC_EVENT_SET: -+ return ntsync_event_set(obj, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 040cbdb39033..af518530bffd 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -48,5 +48,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - #define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) - #define NTSYNC_IOC_MUTEX_KILL _IOW ('N', 0x86, __u32) -+#define NTSYNC_IOC_EVENT_SET _IOR ('N', 0x88, __u32) - - #endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0010-[PATCH_v2_11_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_RESET..patch b/linux-clang/linux6.8-zen/patches/0010-[PATCH_v2_11_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_RESET..patch deleted file mode 100644 index 88cdda0..0000000 --- a/linux-clang/linux6.8-zen/patches/0010-[PATCH_v2_11_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_RESET..patch +++ /dev/null @@ -1,63 +0,0 @@ -This corresponds to the NT syscall NtResetEvent(). - -This sets the event to the unsignaled state, and returns its previous state. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 22 ++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 23 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index edfbf11cafe0..fa4c3fa1e496 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -504,6 +504,26 @@ static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) - return 0; - } - -+static int ntsync_event_reset(struct ntsync_obj *event, void __user *argp) -+{ -+ __u32 prev_state; -+ -+ if (event->type != NTSYNC_TYPE_EVENT) -+ return -EINVAL; -+ -+ spin_lock(&event->lock); -+ -+ prev_state = event->u.event.signaled; -+ event->u.event.signaled = false; -+ -+ spin_unlock(&event->lock); -+ -+ if (put_user(prev_state, (__u32 __user *)argp)) -+ return -EFAULT; -+ -+ return 0; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -529,6 +549,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_mutex_kill(obj, argp); - case NTSYNC_IOC_EVENT_SET: - return ntsync_event_set(obj, argp); -+ case NTSYNC_IOC_EVENT_RESET: -+ return ntsync_event_reset(obj, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index af518530bffd..6963356ee3f7 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -49,5 +49,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) - #define NTSYNC_IOC_MUTEX_KILL _IOW ('N', 0x86, __u32) - #define NTSYNC_IOC_EVENT_SET _IOR ('N', 0x88, __u32) -+#define NTSYNC_IOC_EVENT_RESET _IOR ('N', 0x89, __u32) - - #endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0011-[PATCH_v2_12_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_PULSE..patch b/linux-clang/linux6.8-zen/patches/0011-[PATCH_v2_12_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_PULSE..patch deleted file mode 100644 index 76aa1a7..0000000 --- a/linux-clang/linux6.8-zen/patches/0011-[PATCH_v2_12_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_PULSE..patch +++ /dev/null @@ -1,70 +0,0 @@ -This corresponds to the NT syscall NtPulseEvent(). - -This wakes up any waiters as if the event had been set, but does not set the -event, instead resetting it if it had been signalled. Thus, for a manual-reset -event, all waiters are woken, whereas for an auto-reset event, at most one -waiter is woken. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 10 ++++++++-- - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 9 insertions(+), 2 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index fa4c3fa1e496..b9b4127a6c9f 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -469,7 +469,7 @@ static int ntsync_mutex_kill(struct ntsync_obj *mutex, void __user *argp) - return ret; - } - --static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) -+static int ntsync_event_set(struct ntsync_obj *event, void __user *argp, bool pulse) - { - struct ntsync_device *dev = event->dev; - __u32 prev_state; -@@ -485,6 +485,8 @@ static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) - event->u.event.signaled = true; - try_wake_all_obj(dev, event); - try_wake_any_event(event); -+ if (pulse) -+ event->u.event.signaled = false; - - spin_unlock(&event->lock); - spin_unlock(&dev->wait_all_lock); -@@ -494,6 +496,8 @@ static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) - prev_state = event->u.event.signaled; - event->u.event.signaled = true; - try_wake_any_event(event); -+ if (pulse) -+ event->u.event.signaled = false; - - spin_unlock(&event->lock); - } -@@ -548,9 +552,11 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - case NTSYNC_IOC_MUTEX_KILL: - return ntsync_mutex_kill(obj, argp); - case NTSYNC_IOC_EVENT_SET: -- return ntsync_event_set(obj, argp); -+ return ntsync_event_set(obj, argp, false); - case NTSYNC_IOC_EVENT_RESET: - return ntsync_event_reset(obj, argp); -+ case NTSYNC_IOC_EVENT_PULSE: -+ return ntsync_event_set(obj, argp, true); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 6963356ee3f7..72047f36c45d 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -50,5 +50,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_MUTEX_KILL _IOW ('N', 0x86, __u32) - #define NTSYNC_IOC_EVENT_SET _IOR ('N', 0x88, __u32) - #define NTSYNC_IOC_EVENT_RESET _IOR ('N', 0x89, __u32) -+#define NTSYNC_IOC_EVENT_PULSE _IOR ('N', 0x8a, __u32) - - #endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0012-[PATCH_v2_13_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_READ..patch b/linux-clang/linux6.8-zen/patches/0012-[PATCH_v2_13_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_READ..patch deleted file mode 100644 index e32f7ef..0000000 --- a/linux-clang/linux6.8-zen/patches/0012-[PATCH_v2_13_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_READ..patch +++ /dev/null @@ -1,62 +0,0 @@ -This corresponds to the NT syscall NtQuerySemaphore(). - -This returns the current count and maximum count of the semaphore. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 21 +++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 22 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index b9b4127a6c9f..0daaeeeba051 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -528,6 +528,25 @@ static int ntsync_event_reset(struct ntsync_obj *event, void __user *argp) - return 0; - } - -+static int ntsync_sem_read(struct ntsync_obj *sem, void __user *argp) -+{ -+ struct ntsync_sem_args __user *user_args = argp; -+ struct ntsync_sem_args args; -+ -+ if (sem->type != NTSYNC_TYPE_SEM) -+ return -EINVAL; -+ -+ args.sem = 0; -+ spin_lock(&sem->lock); -+ args.count = sem->u.sem.count; -+ args.max = sem->u.sem.max; -+ spin_unlock(&sem->lock); -+ -+ if (copy_to_user(user_args, &args, sizeof(args))) -+ return -EFAULT; -+ return 0; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -547,6 +566,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - switch (cmd) { - case NTSYNC_IOC_SEM_POST: - return ntsync_sem_post(obj, argp); -+ case NTSYNC_IOC_SEM_READ: -+ return ntsync_sem_read(obj, argp); - case NTSYNC_IOC_MUTEX_UNLOCK: - return ntsync_mutex_unlock(obj, argp); - case NTSYNC_IOC_MUTEX_KILL: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 72047f36c45d..42f51dc4e57e 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -51,5 +51,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_EVENT_SET _IOR ('N', 0x88, __u32) - #define NTSYNC_IOC_EVENT_RESET _IOR ('N', 0x89, __u32) - #define NTSYNC_IOC_EVENT_PULSE _IOR ('N', 0x8a, __u32) -+#define NTSYNC_IOC_SEM_READ _IOR ('N', 0x8b, struct ntsync_sem_args) - - #endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0013-[PATCH_v2_14_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_READ..patch b/linux-clang/linux6.8-zen/patches/0013-[PATCH_v2_14_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_READ..patch deleted file mode 100644 index b97bd13..0000000 --- a/linux-clang/linux6.8-zen/patches/0013-[PATCH_v2_14_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_READ..patch +++ /dev/null @@ -1,64 +0,0 @@ -This corresponds to the NT syscall NtQueryMutant(). - -This returns the recursion count, owner, and abandoned state of the mutex. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 23 +++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 24 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 0daaeeeba051..b07510035c1f 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -547,6 +547,27 @@ static int ntsync_sem_read(struct ntsync_obj *sem, void __user *argp) - return 0; - } - -+static int ntsync_mutex_read(struct ntsync_obj *mutex, void __user *argp) -+{ -+ struct ntsync_mutex_args __user *user_args = argp; -+ struct ntsync_mutex_args args; -+ int ret; -+ -+ if (mutex->type != NTSYNC_TYPE_MUTEX) -+ return -EINVAL; -+ -+ args.mutex = 0; -+ spin_lock(&mutex->lock); -+ args.count = mutex->u.mutex.count; -+ args.owner = mutex->u.mutex.owner; -+ ret = mutex->u.mutex.ownerdead ? -EOWNERDEAD : 0; -+ spin_unlock(&mutex->lock); -+ -+ if (copy_to_user(user_args, &args, sizeof(args))) -+ return -EFAULT; -+ return ret; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -572,6 +593,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_mutex_unlock(obj, argp); - case NTSYNC_IOC_MUTEX_KILL: - return ntsync_mutex_kill(obj, argp); -+ case NTSYNC_IOC_MUTEX_READ: -+ return ntsync_mutex_read(obj, argp); - case NTSYNC_IOC_EVENT_SET: - return ntsync_event_set(obj, argp, false); - case NTSYNC_IOC_EVENT_RESET: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 42f51dc4e57e..25f3296cfabf 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -52,5 +52,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_EVENT_RESET _IOR ('N', 0x89, __u32) - #define NTSYNC_IOC_EVENT_PULSE _IOR ('N', 0x8a, __u32) - #define NTSYNC_IOC_SEM_READ _IOR ('N', 0x8b, struct ntsync_sem_args) -+#define NTSYNC_IOC_MUTEX_READ _IOR ('N', 0x8c, struct ntsync_mutex_args) - - #endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0014-[PATCH_v2_15_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_READ..patch b/linux-clang/linux6.8-zen/patches/0014-[PATCH_v2_15_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_READ..patch deleted file mode 100644 index 476ae09..0000000 --- a/linux-clang/linux6.8-zen/patches/0014-[PATCH_v2_15_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_READ..patch +++ /dev/null @@ -1,62 +0,0 @@ -This corresponds to the NT syscall NtQueryEvent(). - -This returns the signaled state of the event and whether it is manual-reset. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 21 +++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 22 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index b07510035c1f..981a1545192c 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -568,6 +568,25 @@ static int ntsync_mutex_read(struct ntsync_obj *mutex, void __user *argp) - return ret; - } - -+static int ntsync_event_read(struct ntsync_obj *event, void __user *argp) -+{ -+ struct ntsync_event_args __user *user_args = argp; -+ struct ntsync_event_args args; -+ -+ if (event->type != NTSYNC_TYPE_EVENT) -+ return -EINVAL; -+ -+ args.event = 0; -+ spin_lock(&event->lock); -+ args.manual = event->u.event.manual; -+ args.signaled = event->u.event.signaled; -+ spin_unlock(&event->lock); -+ -+ if (copy_to_user(user_args, &args, sizeof(args))) -+ return -EFAULT; -+ return 0; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -601,6 +620,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_event_reset(obj, argp); - case NTSYNC_IOC_EVENT_PULSE: - return ntsync_event_set(obj, argp, true); -+ case NTSYNC_IOC_EVENT_READ: -+ return ntsync_event_read(obj, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 25f3296cfabf..03c95e5a398f 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -53,5 +53,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_EVENT_PULSE _IOR ('N', 0x8a, __u32) - #define NTSYNC_IOC_SEM_READ _IOR ('N', 0x8b, struct ntsync_sem_args) - #define NTSYNC_IOC_MUTEX_READ _IOR ('N', 0x8c, struct ntsync_mutex_args) -+#define NTSYNC_IOC_EVENT_READ _IOR ('N', 0x8d, struct ntsync_event_args) - - #endif --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0015-[PATCH_v2_16_31]_ntsync:_Introduce_alertable_waits..patch b/linux-clang/linux6.8-zen/patches/0015-[PATCH_v2_16_31]_ntsync:_Introduce_alertable_waits..patch deleted file mode 100644 index ce53af5..0000000 --- a/linux-clang/linux6.8-zen/patches/0015-[PATCH_v2_16_31]_ntsync:_Introduce_alertable_waits..patch +++ /dev/null @@ -1,184 +0,0 @@ -NT waits can optionally be made "alertable". This is a special channel for -thread wakeup that is mildly similar to SIGIO. A thread has an internal single -bit of "alerted" state, and if a thread is made alerted while an alertable wait, -the wait will return a special value, consume the "alerted" state, and will not -consume any of its objects. - -Alerts are implemented using events; the user-space NT emulator is expected to -create an internal ntsync event for each thread and pass that event to wait -functions. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 68 ++++++++++++++++++++++++++++++++----- - include/uapi/linux/ntsync.h | 2 +- - 2 files changed, 60 insertions(+), 10 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 981a1545192c..0055b4671808 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -808,22 +808,29 @@ static int setup_wait(struct ntsync_device *dev, - const struct ntsync_wait_args *args, bool all, - struct ntsync_q **ret_q) - { -+ int fds[NTSYNC_MAX_WAIT_COUNT + 1]; - const __u32 count = args->count; -- int fds[NTSYNC_MAX_WAIT_COUNT]; - struct ntsync_q *q; -+ __u32 total_count; - __u32 i, j; - -- if (!args->owner || args->pad) -+ if (!args->owner) - return -EINVAL; - - if (args->count > NTSYNC_MAX_WAIT_COUNT) - return -EINVAL; - -+ total_count = count; -+ if (args->alert) -+ total_count++; -+ - if (copy_from_user(fds, u64_to_user_ptr(args->objs), - array_size(count, sizeof(*fds)))) - return -EFAULT; -+ if (args->alert) -+ fds[count] = args->alert; - -- q = kmalloc(struct_size(q, entries, count), GFP_KERNEL); -+ q = kmalloc(struct_size(q, entries, total_count), GFP_KERNEL); - if (!q) - return -ENOMEM; - q->task = current; -@@ -833,7 +840,7 @@ static int setup_wait(struct ntsync_device *dev, - q->ownerdead = false; - q->count = count; - -- for (i = 0; i < count; i++) { -+ for (i = 0; i < total_count; i++) { - struct ntsync_q_entry *entry = &q->entries[i]; - struct ntsync_obj *obj = get_obj(dev, fds[i]); - -@@ -883,9 +890,9 @@ static void try_wake_any_obj(struct ntsync_obj *obj) - static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - { - struct ntsync_wait_args args; -+ __u32 i, total_count; - struct ntsync_q *q; - int signaled; -- __u32 i; - int ret; - - if (copy_from_user(&args, argp, sizeof(args))) -@@ -895,9 +902,13 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - if (ret < 0) - return ret; - -+ total_count = args.count; -+ if (args.alert) -+ total_count++; -+ - /* queue ourselves */ - -- for (i = 0; i < args.count; i++) { -+ for (i = 0; i < total_count; i++) { - struct ntsync_q_entry *entry = &q->entries[i]; - struct ntsync_obj *obj = entry->obj; - -@@ -906,9 +917,15 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - spin_unlock(&obj->lock); - } - -- /* check if we are already signaled */ -+ /* -+ * Check if we are already signaled. -+ * -+ * Note that the API requires that normal objects are checked before -+ * the alert event. Hence we queue the alert event last, and check -+ * objects in order. -+ */ - -- for (i = 0; i < args.count; i++) { -+ for (i = 0; i < total_count; i++) { - struct ntsync_obj *obj = q->entries[i].obj; - - if (atomic_read(&q->signaled) != -1) -@@ -925,7 +942,7 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - - /* and finally, unqueue */ - -- for (i = 0; i < args.count; i++) { -+ for (i = 0; i < total_count; i++) { - struct ntsync_q_entry *entry = &q->entries[i]; - struct ntsync_obj *obj = entry->obj; - -@@ -985,6 +1002,14 @@ static int ntsync_wait_all(struct ntsync_device *dev, void __user *argp) - */ - list_add_tail(&entry->node, &obj->all_waiters); - } -+ if (args.alert) { -+ struct ntsync_q_entry *entry = &q->entries[args.count]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ spin_lock_nest_lock(&obj->lock, &dev->wait_all_lock); -+ list_add_tail(&entry->node, &obj->any_waiters); -+ spin_unlock(&obj->lock); -+ } - - /* check if we are already signaled */ - -@@ -992,6 +1017,21 @@ static int ntsync_wait_all(struct ntsync_device *dev, void __user *argp) - - spin_unlock(&dev->wait_all_lock); - -+ /* -+ * Check if the alert event is signaled, making sure to do so only -+ * after checking if the other objects are signaled. -+ */ -+ -+ if (args.alert) { -+ struct ntsync_obj *obj = q->entries[args.count].obj; -+ -+ if (atomic_read(&q->signaled) == -1) { -+ spin_lock(&obj->lock); -+ try_wake_any_obj(obj); -+ spin_unlock(&obj->lock); -+ } -+ } -+ - /* sleep */ - - ret = ntsync_schedule(q, &args); -@@ -1014,6 +1054,16 @@ static int ntsync_wait_all(struct ntsync_device *dev, void __user *argp) - - put_obj(obj); - } -+ if (args.alert) { -+ struct ntsync_q_entry *entry = &q->entries[args.count]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ spin_lock_nest_lock(&obj->lock, &dev->wait_all_lock); -+ list_del(&entry->node); -+ spin_unlock(&obj->lock); -+ -+ put_obj(obj); -+ } - - spin_unlock(&dev->wait_all_lock); - -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 03c95e5a398f..555ae81b479a 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -34,7 +34,7 @@ struct ntsync_wait_args { - __u32 count; - __u32 owner; - __u32 index; -- __u32 pad; -+ __u32 alert; - }; - - #define NTSYNC_MAX_WAIT_COUNT 64 --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0016-[PATCH_v2_17_31]_ntsync:_Allow_waits_to_use_the_REALTIME_clock..patch b/linux-clang/linux6.8-zen/patches/0016-[PATCH_v2_17_31]_ntsync:_Allow_waits_to_use_the_REALTIME_clock..patch deleted file mode 100644 index 6e15e88..0000000 --- a/linux-clang/linux6.8-zen/patches/0016-[PATCH_v2_17_31]_ntsync:_Allow_waits_to_use_the_REALTIME_clock..patch +++ /dev/null @@ -1,79 +0,0 @@ -NtWaitForMultipleObjects() can receive a timeout in two forms, relative or -absolute. Relative timeouts are unaffected by changes to the system time and do -not count down while the system suspends; for absolute timeouts the opposite is -true. - -In order to make the interface and implementation simpler, the ntsync driver -only deals in absolute timeouts. However, we need to be able to emulate both -behaviours apropos suspension and time adjustment, which is achieved by allowing -either the MONOTONIC or REALTIME clock to be used. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 9 ++++++++- - include/uapi/linux/ntsync.h | 4 ++++ - 2 files changed, 12 insertions(+), 1 deletion(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 0055b4671808..f54c81dada3d 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -778,11 +778,15 @@ static void put_obj(struct ntsync_obj *obj) - static int ntsync_schedule(const struct ntsync_q *q, const struct ntsync_wait_args *args) - { - ktime_t timeout = ns_to_ktime(args->timeout); -+ clockid_t clock = CLOCK_MONOTONIC; - ktime_t *timeout_ptr; - int ret = 0; - - timeout_ptr = (args->timeout == U64_MAX ? NULL : &timeout); - -+ if (args->flags & NTSYNC_WAIT_REALTIME) -+ clock = CLOCK_REALTIME; -+ - do { - if (signal_pending(current)) { - ret = -ERESTARTSYS; -@@ -794,7 +798,7 @@ static int ntsync_schedule(const struct ntsync_q *q, const struct ntsync_wait_ar - ret = 0; - break; - } -- ret = schedule_hrtimeout(timeout_ptr, HRTIMER_MODE_ABS); -+ ret = schedule_hrtimeout_range_clock(timeout_ptr, 0, HRTIMER_MODE_ABS, clock); - } while (ret < 0); - __set_current_state(TASK_RUNNING); - -@@ -817,6 +821,9 @@ static int setup_wait(struct ntsync_device *dev, - if (!args->owner) - return -EINVAL; - -+ if (args->pad || (args->flags & ~NTSYNC_WAIT_REALTIME)) -+ return -EINVAL; -+ - if (args->count > NTSYNC_MAX_WAIT_COUNT) - return -EINVAL; - -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 555ae81b479a..b5e835d8dba8 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -28,6 +28,8 @@ struct ntsync_event_args { - __u32 signaled; - }; - -+#define NTSYNC_WAIT_REALTIME 0x1 -+ - struct ntsync_wait_args { - __u64 timeout; - __u64 objs; -@@ -35,6 +37,8 @@ struct ntsync_wait_args { - __u32 owner; - __u32 index; - __u32 alert; -+ __u32 flags; -+ __u32 pad; - }; - - #define NTSYNC_MAX_WAIT_COUNT 64 --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0017-[PATCH_v2_18_31]_selftests:_ntsync:_Add_some_tests_for_semaphore\n_state..patch" "b/linux-clang/linux6.8-zen/patches/0017-[PATCH_v2_18_31]_selftests:_ntsync:_Add_some_tests_for_semaphore\n_state..patch" deleted file mode 100644 index 5d8c716..0000000 --- "a/linux-clang/linux6.8-zen/patches/0017-[PATCH_v2_18_31]_selftests:_ntsync:_Add_some_tests_for_semaphore\n_state..patch" +++ /dev/null @@ -1,208 +0,0 @@ -Wine has tests for its synchronization primitives, but these are more accessible -to kernel developers, and also allow us to test some edge cases that Wine does -not care about. - -This patch adds tests for semaphore-specific ioctls NTSYNC_IOC_SEM_POST and -NTSYNC_IOC_SEM_READ, and waiting on semaphores. - -Signed-off-by: Elizabeth Figura ---- - tools/testing/selftests/Makefile | 1 + - .../testing/selftests/drivers/ntsync/Makefile | 8 + - tools/testing/selftests/drivers/ntsync/config | 1 + - .../testing/selftests/drivers/ntsync/ntsync.c | 149 ++++++++++++++++++ - 4 files changed, 159 insertions(+) - 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 - -diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile -index 15b6a111c3be..6c714a4e6478 100644 ---- a/tools/testing/selftests/Makefile -+++ b/tools/testing/selftests/Makefile -@@ -15,6 +15,7 @@ TARGETS += cpu-hotplug - TARGETS += damon - TARGETS += dmabuf-heaps - TARGETS += drivers/dma-buf -+TARGETS += drivers/ntsync - TARGETS += drivers/s390x/uvdevice - TARGETS += drivers/net/bonding - TARGETS += drivers/net/team -diff --git a/tools/testing/selftests/drivers/ntsync/Makefile b/tools/testing/selftests/drivers/ntsync/Makefile -new file mode 100644 -index 000000000000..a34da5ccacf0 ---- /dev/null -+++ b/tools/testing/selftests/drivers/ntsync/Makefile -@@ -0,0 +1,8 @@ -+# SPDX-LICENSE-IDENTIFIER: GPL-2.0-only -+TEST_GEN_PROGS := ntsync -+ -+top_srcdir =../../../../.. -+CFLAGS += -I$(top_srcdir)/usr/include -+LDLIBS += -lpthread -+ -+include ../../lib.mk -diff --git a/tools/testing/selftests/drivers/ntsync/config b/tools/testing/selftests/drivers/ntsync/config -new file mode 100644 -index 000000000000..60539c826d06 ---- /dev/null -+++ b/tools/testing/selftests/drivers/ntsync/config -@@ -0,0 +1 @@ -+CONFIG_WINESYNC=y -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -new file mode 100644 -index 000000000000..1e145c6dfded ---- /dev/null -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -0,0 +1,149 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Various unit tests for the "ntsync" synchronization primitive driver. -+ * -+ * Copyright (C) 2021-2022 Elizabeth Figura -+ */ -+ -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+#include -+#include -+#include "../../kselftest_harness.h" -+ -+static int read_sem_state(int sem, __u32 *count, __u32 *max) -+{ -+ struct ntsync_sem_args args; -+ int ret; -+ -+ memset(&args, 0xcc, sizeof(args)); -+ ret = ioctl(sem, NTSYNC_IOC_SEM_READ, &args); -+ *count = args.count; -+ *max = args.max; -+ return ret; -+} -+ -+#define check_sem_state(sem, count, max) \ -+ ({ \ -+ __u32 __count, __max; \ -+ int ret = read_sem_state((sem), &__count, &__max); \ -+ EXPECT_EQ(0, ret); \ -+ EXPECT_EQ((count), __count); \ -+ EXPECT_EQ((max), __max); \ -+ }) -+ -+static int post_sem(int sem, __u32 *count) -+{ -+ return ioctl(sem, NTSYNC_IOC_SEM_POST, count); -+} -+ -+static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) -+{ -+ struct ntsync_wait_args args = {0}; -+ struct timespec timeout; -+ int ret; -+ -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ -+ args.timeout = timeout.tv_sec * 1000000000 + timeout.tv_nsec; -+ args.count = count; -+ args.objs = (uintptr_t)objs; -+ args.owner = owner; -+ args.index = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_WAIT_ANY, &args); -+ *index = args.index; -+ return ret; -+} -+ -+TEST(semaphore_state) -+{ -+ struct ntsync_sem_args sem_args; -+ struct timespec timeout; -+ __u32 count, index; -+ int fd, ret, sem; -+ -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 3; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ sem_args.count = 2; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ sem = sem_args.sem; -+ check_sem_state(sem, 2, 2); -+ -+ count = 0; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, count); -+ check_sem_state(sem, 2, 2); -+ -+ count = 1; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOVERFLOW, errno); -+ check_sem_state(sem, 2, 2); -+ -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem, 1, 2); -+ -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem, 0, 2); -+ -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ count = 3; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOVERFLOW, errno); -+ check_sem_state(sem, 0, 2); -+ -+ count = 2; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ check_sem_state(sem, 2, 2); -+ -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ -+ count = 1; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ check_sem_state(sem, 1, 2); -+ -+ count = ~0u; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOVERFLOW, errno); -+ check_sem_state(sem, 1, 2); -+ -+ close(sem); -+ -+ close(fd); -+} -+ -+TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0018-[PATCH_v2_19_31]_selftests:_ntsync:_Add_some_tests_for_mutex\n_state..patch" "b/linux-clang/linux6.8-zen/patches/0018-[PATCH_v2_19_31]_selftests:_ntsync:_Add_some_tests_for_mutex\n_state..patch" deleted file mode 100644 index 316e7d1..0000000 --- "a/linux-clang/linux6.8-zen/patches/0018-[PATCH_v2_19_31]_selftests:_ntsync:_Add_some_tests_for_mutex\n_state..patch" +++ /dev/null @@ -1,222 +0,0 @@ -Test mutex-specific ioctls NTSYNC_IOC_MUTEX_UNLOCK and NTSYNC_IOC_MUTEX_READ, -and waiting on mutexes. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 196 ++++++++++++++++++ - 1 file changed, 196 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 1e145c6dfded..7cd0f40594fd 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -40,6 +40,39 @@ static int post_sem(int sem, __u32 *count) - return ioctl(sem, NTSYNC_IOC_SEM_POST, count); - } - -+static int read_mutex_state(int mutex, __u32 *count, __u32 *owner) -+{ -+ struct ntsync_mutex_args args; -+ int ret; -+ -+ memset(&args, 0xcc, sizeof(args)); -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &args); -+ *count = args.count; -+ *owner = args.owner; -+ return ret; -+} -+ -+#define check_mutex_state(mutex, count, owner) \ -+ ({ \ -+ __u32 __count, __owner; \ -+ int ret = read_mutex_state((mutex), &__count, &__owner); \ -+ EXPECT_EQ(0, ret); \ -+ EXPECT_EQ((count), __count); \ -+ EXPECT_EQ((owner), __owner); \ -+ }) -+ -+static int unlock_mutex(int mutex, __u32 owner, __u32 *count) -+{ -+ struct ntsync_mutex_args args; -+ int ret; -+ -+ args.owner = owner; -+ args.count = 0xdeadbeef; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_UNLOCK, &args); -+ *count = args.count; -+ return ret; -+} -+ - static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) - { - struct ntsync_wait_args args = {0}; -@@ -146,4 +179,167 @@ TEST(semaphore_state) - close(fd); - } - -+TEST(mutex_state) -+{ -+ struct ntsync_mutex_args mutex_args; -+ __u32 owner, count, index; -+ struct timespec timeout; -+ int fd, ret, mutex; -+ -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = 0; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 2; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = 2; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ mutex = mutex_args.mutex; -+ check_mutex_state(mutex, 2, 123); -+ -+ ret = unlock_mutex(mutex, 0, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ ret = unlock_mutex(mutex, 456, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EPERM, errno); -+ check_mutex_state(mutex, 2, 123); -+ -+ ret = unlock_mutex(mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, count); -+ check_mutex_state(mutex, 1, 123); -+ -+ ret = unlock_mutex(mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, count); -+ check_mutex_state(mutex, 0, 0); -+ -+ ret = unlock_mutex(mutex, 123, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EPERM, errno); -+ -+ ret = wait_any(fd, 1, &mutex, 456, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 1, 456); -+ -+ ret = wait_any(fd, 1, &mutex, 456, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 2, 456); -+ -+ ret = unlock_mutex(mutex, 456, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, count); -+ check_mutex_state(mutex, 1, 456); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ owner = 0; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ owner = 123; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EPERM, errno); -+ check_mutex_state(mutex, 1, 456); -+ -+ owner = 456; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(0, ret); -+ -+ memset(&mutex_args, 0xcc, sizeof(mutex_args)); -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, mutex_args.count); -+ EXPECT_EQ(0, mutex_args.owner); -+ -+ memset(&mutex_args, 0xcc, sizeof(mutex_args)); -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, mutex_args.count); -+ EXPECT_EQ(0, mutex_args.owner); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 1, 123); -+ -+ owner = 123; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(0, ret); -+ -+ memset(&mutex_args, 0xcc, sizeof(mutex_args)); -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, mutex_args.count); -+ EXPECT_EQ(0, mutex_args.owner); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 1, 123); -+ -+ close(mutex); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 0; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ mutex = mutex_args.mutex; -+ check_mutex_state(mutex, 0, 0); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 1, 123); -+ -+ close(mutex); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = ~0u; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ mutex = mutex_args.mutex; -+ check_mutex_state(mutex, ~0u, 123); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ close(mutex); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0019-[PATCH_v2_20_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ANY..patch" "b/linux-clang/linux6.8-zen/patches/0019-[PATCH_v2_20_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ANY..patch" deleted file mode 100644 index 6484738..0000000 --- "a/linux-clang/linux6.8-zen/patches/0019-[PATCH_v2_20_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ANY..patch" +++ /dev/null @@ -1,139 +0,0 @@ -Test basic synchronous functionality of NTSYNC_IOC_WAIT_ANY, when objects are -considered signaled or not signaled, and how they are affected by a successful -wait. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 119 ++++++++++++++++++ - 1 file changed, 119 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 7cd0f40594fd..40ad8cbd3138 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -342,4 +342,123 @@ TEST(mutex_state) - close(fd); - } - -+TEST(test_wait_any) -+{ -+ int objs[NTSYNC_MAX_WAIT_COUNT + 1], fd, ret; -+ struct ntsync_mutex_args mutex_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ __u32 owner, index, count, i; -+ struct timespec timeout; -+ -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 2; -+ sem_args.max = 3; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 0; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ -+ objs[0] = sem_args.sem; -+ objs[1] = mutex_args.mutex; -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 0, 0); -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 0, 0); -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ count = 1; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 2, 123); -+ -+ ret = wait_any(fd, 2, objs, 456, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ owner = 123; -+ ret = ioctl(mutex_args.mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any(fd, 2, objs, 456, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(1, index); -+ -+ ret = wait_any(fd, 2, objs, 456, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, index); -+ -+ /* test waiting on the same object twice */ -+ count = 2; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ -+ objs[0] = objs[1] = sem_args.sem; -+ ret = wait_any(fd, 2, objs, 456, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 1, 3); -+ -+ ret = wait_any(fd, 0, NULL, 456, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ for (i = 0; i < NTSYNC_MAX_WAIT_COUNT + 1; ++i) -+ objs[i] = sem_args.sem; -+ -+ ret = wait_any(fd, NTSYNC_MAX_WAIT_COUNT, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = wait_any(fd, NTSYNC_MAX_WAIT_COUNT + 1, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ ret = wait_any(fd, -1, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ close(sem_args.sem); -+ close(mutex_args.mutex); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0020-[PATCH_v2_21_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ALL..patch" "b/linux-clang/linux6.8-zen/patches/0020-[PATCH_v2_21_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ALL..patch" deleted file mode 100644 index ebe93e0..0000000 --- "a/linux-clang/linux6.8-zen/patches/0020-[PATCH_v2_21_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ALL..patch" +++ /dev/null @@ -1,136 +0,0 @@ -Test basic synchronous functionality of NTSYNC_IOC_WAIT_ALL, and when objects -are considered simultaneously signaled. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 99 ++++++++++++++++++- - 1 file changed, 97 insertions(+), 2 deletions(-) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 40ad8cbd3138..c0f372167557 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -73,7 +73,8 @@ static int unlock_mutex(int mutex, __u32 owner, __u32 *count) - return ret; - } - --static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) -+static int wait_objs(int fd, unsigned long request, __u32 count, -+ const int *objs, __u32 owner, __u32 *index) - { - struct ntsync_wait_args args = {0}; - struct timespec timeout; -@@ -86,11 +87,21 @@ static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *in - args.objs = (uintptr_t)objs; - args.owner = owner; - args.index = 0xdeadbeef; -- ret = ioctl(fd, NTSYNC_IOC_WAIT_ANY, &args); -+ ret = ioctl(fd, request, &args); - *index = args.index; - return ret; - } - -+static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) -+{ -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ANY, count, objs, owner, index); -+} -+ -+static int wait_all(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) -+{ -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ALL, count, objs, owner, index); -+} -+ - TEST(semaphore_state) - { - struct ntsync_sem_args sem_args; -@@ -461,4 +472,88 @@ TEST(test_wait_any) - close(fd); - } - -+TEST(test_wait_all) -+{ -+ struct ntsync_mutex_args mutex_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ __u32 owner, index, count; -+ int objs[2], fd, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 2; -+ sem_args.max = 3; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 0; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ -+ objs[0] = sem_args.sem; -+ objs[1] = mutex_args.mutex; -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ ret = wait_all(fd, 2, objs, 456, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 2, 123); -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 2, 123); -+ -+ count = 3; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 2, 3); -+ check_mutex_state(mutex_args.mutex, 3, 123); -+ -+ owner = 123; -+ ret = ioctl(mutex_args.mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ /* test waiting on the same object twice */ -+ objs[0] = objs[1] = sem_args.sem; -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ close(sem_args.sem); -+ close(mutex_args.mutex); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0021-[PATCH_v2_22_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ANY..patch" "b/linux-clang/linux6.8-zen/patches/0021-[PATCH_v2_22_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ANY..patch" deleted file mode 100644 index d813930..0000000 --- "a/linux-clang/linux6.8-zen/patches/0021-[PATCH_v2_22_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ANY..patch" +++ /dev/null @@ -1,169 +0,0 @@ -Test contended "wait-for-any" waits, to make sure that scheduling and wakeup -logic works correctly. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 150 ++++++++++++++++++ - 1 file changed, 150 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index c0f372167557..993f5db23768 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -556,4 +556,154 @@ TEST(test_wait_all) - close(fd); - } - -+struct wake_args { -+ int fd; -+ int obj; -+}; -+ -+struct wait_args { -+ int fd; -+ unsigned long request; -+ struct ntsync_wait_args *args; -+ int ret; -+ int err; -+}; -+ -+static void *wait_thread(void *arg) -+{ -+ struct wait_args *args = arg; -+ -+ args->ret = ioctl(args->fd, args->request, args->args); -+ args->err = errno; -+ return NULL; -+} -+ -+static __u64 get_abs_timeout(unsigned int ms) -+{ -+ struct timespec timeout; -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ return (timeout.tv_sec * 1000000000) + timeout.tv_nsec + (ms * 1000000); -+} -+ -+static int wait_for_thread(pthread_t thread, unsigned int ms) -+{ -+ struct timespec timeout; -+ -+ clock_gettime(CLOCK_REALTIME, &timeout); -+ timeout.tv_nsec += ms * 1000000; -+ timeout.tv_sec += (timeout.tv_nsec / 1000000000); -+ timeout.tv_nsec %= 1000000000; -+ return pthread_timedjoin_np(thread, NULL, &timeout); -+} -+ -+TEST(wake_any) -+{ -+ struct ntsync_mutex_args mutex_args = {0}; -+ struct ntsync_wait_args wait_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ struct wait_args thread_args; -+ int objs[2], fd, ret; -+ __u32 count, index; -+ pthread_t thread; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 0; -+ sem_args.max = 3; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = 1; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ -+ objs[0] = sem_args.sem; -+ objs[1] = mutex_args.mutex; -+ -+ /* test waking the semaphore */ -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.objs = (uintptr_t)objs; -+ wait_args.count = 2; -+ wait_args.owner = 456; -+ wait_args.index = 0xdeadbeef; -+ thread_args.fd = fd; -+ thread_args.args = &wait_args; -+ thread_args.request = NTSYNC_IOC_WAIT_ANY; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ count = 1; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ check_sem_state(sem_args.sem, 0, 3); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(0, wait_args.index); -+ -+ /* test waking the mutex */ -+ -+ /* first grab it again for owner 123 */ -+ ret = wait_any(fd, 1, &mutex_args.mutex, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.owner = 456; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = unlock_mutex(mutex_args.mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, count); -+ -+ ret = pthread_tryjoin_np(thread, NULL); -+ EXPECT_EQ(EBUSY, ret); -+ -+ ret = unlock_mutex(mutex_args.mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, mutex_args.count); -+ check_mutex_state(mutex_args.mutex, 1, 456); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ /* delete an object while it's being waited on */ -+ -+ wait_args.timeout = get_abs_timeout(200); -+ wait_args.owner = 123; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ close(sem_args.sem); -+ close(mutex_args.mutex); -+ -+ ret = wait_for_thread(thread, 200); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(-1, thread_args.ret); -+ EXPECT_EQ(ETIMEDOUT, thread_args.err); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0022-[PATCH_v2_23_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ALL..patch" "b/linux-clang/linux6.8-zen/patches/0022-[PATCH_v2_23_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ALL..patch" deleted file mode 100644 index 053e2c7..0000000 --- "a/linux-clang/linux6.8-zen/patches/0022-[PATCH_v2_23_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ALL..patch" +++ /dev/null @@ -1,118 +0,0 @@ -Test contended "wait-for-all" waits, to make sure that scheduling and wakeup -logic works correctly, and that the wait only exits once objects are all -simultaneously signaled. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 98 +++++++++++++++++++ - 1 file changed, 98 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 993f5db23768..b77fb0b2c4b1 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -706,4 +706,102 @@ TEST(wake_any) - close(fd); - } - -+TEST(wake_all) -+{ -+ struct ntsync_mutex_args mutex_args = {0}; -+ struct ntsync_wait_args wait_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ struct wait_args thread_args; -+ int objs[2], fd, ret; -+ __u32 count, index; -+ pthread_t thread; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 0; -+ sem_args.max = 3; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = 1; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ -+ objs[0] = sem_args.sem; -+ objs[1] = mutex_args.mutex; -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.objs = (uintptr_t)objs; -+ wait_args.count = 2; -+ wait_args.owner = 456; -+ thread_args.fd = fd; -+ thread_args.args = &wait_args; -+ thread_args.request = NTSYNC_IOC_WAIT_ALL; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ count = 1; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ -+ ret = pthread_tryjoin_np(thread, NULL); -+ EXPECT_EQ(EBUSY, ret); -+ -+ check_sem_state(sem_args.sem, 1, 3); -+ -+ ret = wait_any(fd, 1, &sem_args.sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = unlock_mutex(mutex_args.mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, count); -+ -+ ret = pthread_tryjoin_np(thread, NULL); -+ EXPECT_EQ(EBUSY, ret); -+ -+ check_mutex_state(mutex_args.mutex, 0, 0); -+ -+ count = 2; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 1, 456); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ -+ /* delete an object while it's being waited on */ -+ -+ wait_args.timeout = get_abs_timeout(200); -+ wait_args.owner = 123; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ close(sem_args.sem); -+ close(mutex_args.mutex); -+ -+ ret = wait_for_thread(thread, 200); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(-1, thread_args.ret); -+ EXPECT_EQ(ETIMEDOUT, thread_args.err); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0023-[PATCH_v2_24_31]_selftests:_ntsync:_Add_some_tests_for\n_manual-reset_event_state..patch" "b/linux-clang/linux6.8-zen/patches/0023-[PATCH_v2_24_31]_selftests:_ntsync:_Add_some_tests_for\n_manual-reset_event_state..patch" deleted file mode 100644 index ace9ac0..0000000 --- "a/linux-clang/linux6.8-zen/patches/0023-[PATCH_v2_24_31]_selftests:_ntsync:_Add_some_tests_for\n_manual-reset_event_state..patch" +++ /dev/null @@ -1,118 +0,0 @@ -Test event-specific ioctls NTSYNC_IOC_EVENT_SET, NTSYNC_IOC_EVENT_RESET, -NTSYNC_IOC_EVENT_PULSE, NTSYNC_IOC_EVENT_READ for manual-reset events, and -waiting on manual-reset events. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 89 +++++++++++++++++++ - 1 file changed, 89 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index b77fb0b2c4b1..b6481c2b85cc 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -73,6 +73,27 @@ static int unlock_mutex(int mutex, __u32 owner, __u32 *count) - return ret; - } - -+static int read_event_state(int event, __u32 *signaled, __u32 *manual) -+{ -+ struct ntsync_event_args args; -+ int ret; -+ -+ memset(&args, 0xcc, sizeof(args)); -+ ret = ioctl(event, NTSYNC_IOC_EVENT_READ, &args); -+ *signaled = args.signaled; -+ *manual = args.manual; -+ return ret; -+} -+ -+#define check_event_state(event, signaled, manual) \ -+ ({ \ -+ __u32 __signaled, __manual; \ -+ int ret = read_event_state((event), &__signaled, &__manual); \ -+ EXPECT_EQ(0, ret); \ -+ EXPECT_EQ((signaled), __signaled); \ -+ EXPECT_EQ((manual), __manual); \ -+ }) -+ - static int wait_objs(int fd, unsigned long request, __u32 count, - const int *objs, __u32 owner, __u32 *index) - { -@@ -353,6 +374,74 @@ TEST(mutex_state) - close(fd); - } - -+TEST(manual_event_state) -+{ -+ struct ntsync_event_args event_args; -+ __u32 index, signaled; -+ int fd, event, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ event_args.manual = 1; -+ event_args.signaled = 0; -+ event_args.event = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, event_args.event); -+ event = event_args.event; -+ check_event_state(event, 0, 1); -+ -+ signaled = 0xdeadbeef; -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 1, 1); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 1, 1); -+ -+ ret = wait_any(fd, 1, &event, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_event_state(event, 1, 1); -+ -+ signaled = 0xdeadbeef; -+ ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 0, 1); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 0, 1); -+ -+ ret = wait_any(fd, 1, &event, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 0, 1); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 0, 1); -+ -+ close(event); -+ -+ close(fd); -+} -+ - TEST(test_wait_any) - { - int objs[NTSYNC_MAX_WAIT_COUNT + 1], fd, ret; --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0024-[PATCH_v2_25_31]_selftests:_ntsync:_Add_some_tests_for_auto-reset\n_event_state..patch" "b/linux-clang/linux6.8-zen/patches/0024-[PATCH_v2_25_31]_selftests:_ntsync:_Add_some_tests_for_auto-reset\n_event_state..patch" deleted file mode 100644 index 3989a16..0000000 --- "a/linux-clang/linux6.8-zen/patches/0024-[PATCH_v2_25_31]_selftests:_ntsync:_Add_some_tests_for_auto-reset\n_event_state..patch" +++ /dev/null @@ -1,81 +0,0 @@ -Test event-specific ioctls NTSYNC_IOC_EVENT_SET, NTSYNC_IOC_EVENT_RESET, -NTSYNC_IOC_EVENT_PULSE, NTSYNC_IOC_EVENT_READ for auto-reset events, and -waiting on auto-reset events. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 59 +++++++++++++++++++ - 1 file changed, 59 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index b6481c2b85cc..12ccb4ec28e4 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -442,6 +442,65 @@ TEST(manual_event_state) - close(fd); - } - -+TEST(auto_event_state) -+{ -+ struct ntsync_event_args event_args; -+ __u32 index, signaled; -+ int fd, event, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ event_args.manual = 0; -+ event_args.signaled = 1; -+ event_args.event = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, event_args.event); -+ event = event_args.event; -+ -+ check_event_state(event, 1, 0); -+ -+ signaled = 0xdeadbeef; -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 1, 0); -+ -+ ret = wait_any(fd, 1, &event, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_event_state(event, 0, 0); -+ -+ signaled = 0xdeadbeef; -+ ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 0, 0); -+ -+ ret = wait_any(fd, 1, &event, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 0, 0); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 0, 0); -+ -+ close(event); -+ -+ close(fd); -+} -+ - TEST(test_wait_any) - { - int objs[NTSYNC_MAX_WAIT_COUNT + 1], fd, ret; --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0025-[PATCH_v2_26_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_events..patch" "b/linux-clang/linux6.8-zen/patches/0025-[PATCH_v2_26_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_events..patch" deleted file mode 100644 index 832a88f..0000000 --- "a/linux-clang/linux6.8-zen/patches/0025-[PATCH_v2_26_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_events..patch" +++ /dev/null @@ -1,259 +0,0 @@ -Expand the contended wait tests, which previously only covered events and -semaphores, to cover events as well. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 151 +++++++++++++++++- - 1 file changed, 147 insertions(+), 4 deletions(-) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 12ccb4ec28e4..5d17eff6a370 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -622,6 +622,7 @@ TEST(test_wait_any) - - TEST(test_wait_all) - { -+ struct ntsync_event_args event_args = {0}; - struct ntsync_mutex_args mutex_args = {0}; - struct ntsync_sem_args sem_args = {0}; - __u32 owner, index, count; -@@ -644,6 +645,11 @@ TEST(test_wait_all) - EXPECT_EQ(0, ret); - EXPECT_NE(0xdeadbeef, mutex_args.mutex); - -+ event_args.manual = true; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ - objs[0] = sem_args.sem; - objs[1] = mutex_args.mutex; - -@@ -692,6 +698,14 @@ TEST(test_wait_all) - check_sem_state(sem_args.sem, 1, 3); - check_mutex_state(mutex_args.mutex, 1, 123); - -+ objs[0] = sem_args.sem; -+ objs[1] = event_args.event; -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_event_state(event_args.event, 1, 1); -+ - /* test waiting on the same object twice */ - objs[0] = objs[1] = sem_args.sem; - ret = wait_all(fd, 2, objs, 123, &index); -@@ -700,6 +714,7 @@ TEST(test_wait_all) - - close(sem_args.sem); - close(mutex_args.mutex); -+ close(event_args.event); - - close(fd); - } -@@ -746,12 +761,13 @@ static int wait_for_thread(pthread_t thread, unsigned int ms) - - TEST(wake_any) - { -+ struct ntsync_event_args event_args = {0}; - struct ntsync_mutex_args mutex_args = {0}; - struct ntsync_wait_args wait_args = {0}; - struct ntsync_sem_args sem_args = {0}; - struct wait_args thread_args; -+ __u32 count, index, signaled; - int objs[2], fd, ret; -- __u32 count, index; - pthread_t thread; - - fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -@@ -833,10 +849,101 @@ TEST(wake_any) - EXPECT_EQ(0, thread_args.ret); - EXPECT_EQ(1, wait_args.index); - -+ /* test waking events */ -+ -+ event_args.manual = false; -+ event_args.signaled = false; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ objs[1] = event_args.event; -+ wait_args.timeout = get_abs_timeout(1000); -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event_args.event, 0, 0); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event_args.event, 0, 0); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ close(event_args.event); -+ -+ event_args.manual = true; -+ event_args.signaled = false; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ objs[1] = event_args.event; -+ wait_args.timeout = get_abs_timeout(1000); -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event_args.event, 1, 1); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event_args.event, 0, 1); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ close(event_args.event); -+ - /* delete an object while it's being waited on */ - - wait_args.timeout = get_abs_timeout(200); - wait_args.owner = 123; -+ objs[1] = mutex_args.mutex; - ret = pthread_create(&thread, NULL, wait_thread, &thread_args); - EXPECT_EQ(0, ret); - -@@ -856,12 +963,14 @@ TEST(wake_any) - - TEST(wake_all) - { -+ struct ntsync_event_args manual_event_args = {0}; -+ struct ntsync_event_args auto_event_args = {0}; - struct ntsync_mutex_args mutex_args = {0}; - struct ntsync_wait_args wait_args = {0}; - struct ntsync_sem_args sem_args = {0}; - struct wait_args thread_args; -- int objs[2], fd, ret; -- __u32 count, index; -+ __u32 count, index, signaled; -+ int objs[4], fd, ret; - pthread_t thread; - - fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -@@ -881,12 +990,24 @@ TEST(wake_all) - EXPECT_EQ(0, ret); - EXPECT_NE(0xdeadbeef, mutex_args.mutex); - -+ manual_event_args.manual = true; -+ manual_event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &manual_event_args); -+ EXPECT_EQ(0, ret); -+ -+ auto_event_args.manual = false; -+ auto_event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &auto_event_args); -+ EXPECT_EQ(0, ret); -+ - objs[0] = sem_args.sem; - objs[1] = mutex_args.mutex; -+ objs[2] = manual_event_args.event; -+ objs[3] = auto_event_args.event; - - wait_args.timeout = get_abs_timeout(1000); - wait_args.objs = (uintptr_t)objs; -- wait_args.count = 2; -+ wait_args.count = 4; - wait_args.owner = 456; - thread_args.fd = fd; - thread_args.args = &wait_args; -@@ -920,12 +1041,32 @@ TEST(wake_all) - - check_mutex_state(mutex_args.mutex, 0, 0); - -+ ret = ioctl(manual_event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ - count = 2; - ret = post_sem(sem_args.sem, &count); - EXPECT_EQ(0, ret); - EXPECT_EQ(0, count); -+ check_sem_state(sem_args.sem, 2, 3); -+ -+ ret = ioctl(auto_event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ -+ ret = ioctl(manual_event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ -+ ret = ioctl(auto_event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ - check_sem_state(sem_args.sem, 1, 3); - check_mutex_state(mutex_args.mutex, 1, 456); -+ check_event_state(manual_event_args.event, 1, 1); -+ check_event_state(auto_event_args.event, 0, 0); - - ret = wait_for_thread(thread, 100); - EXPECT_EQ(0, ret); -@@ -943,6 +1084,8 @@ TEST(wake_all) - - close(sem_args.sem); - close(mutex_args.mutex); -+ close(manual_event_args.event); -+ close(auto_event_args.event); - - ret = wait_for_thread(thread, 200); - EXPECT_EQ(0, ret); --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0026-[PATCH_v2_27_31]_selftests:_ntsync:_Add_tests_for_alertable_waits..patch b/linux-clang/linux6.8-zen/patches/0026-[PATCH_v2_27_31]_selftests:_ntsync:_Add_tests_for_alertable_waits..patch deleted file mode 100644 index b8f967b..0000000 --- a/linux-clang/linux6.8-zen/patches/0026-[PATCH_v2_27_31]_selftests:_ntsync:_Add_tests_for_alertable_waits..patch +++ /dev/null @@ -1,223 +0,0 @@ -Test the "alert" functionality of NTSYNC_IOC_WAIT_ALL and NTSYNC_IOC_WAIT_ANY, -when a wait is woken with an alert and when it is woken by an object. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 179 +++++++++++++++++- - 1 file changed, 176 insertions(+), 3 deletions(-) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 5d17eff6a370..5465a16d38b3 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -95,7 +95,7 @@ static int read_event_state(int event, __u32 *signaled, __u32 *manual) - }) - - static int wait_objs(int fd, unsigned long request, __u32 count, -- const int *objs, __u32 owner, __u32 *index) -+ const int *objs, __u32 owner, int alert, __u32 *index) - { - struct ntsync_wait_args args = {0}; - struct timespec timeout; -@@ -108,6 +108,7 @@ static int wait_objs(int fd, unsigned long request, __u32 count, - args.objs = (uintptr_t)objs; - args.owner = owner; - args.index = 0xdeadbeef; -+ args.alert = alert; - ret = ioctl(fd, request, &args); - *index = args.index; - return ret; -@@ -115,12 +116,26 @@ static int wait_objs(int fd, unsigned long request, __u32 count, - - static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) - { -- return wait_objs(fd, NTSYNC_IOC_WAIT_ANY, count, objs, owner, index); -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ANY, count, objs, owner, 0, index); - } - - static int wait_all(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) - { -- return wait_objs(fd, NTSYNC_IOC_WAIT_ALL, count, objs, owner, index); -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ALL, count, objs, owner, 0, index); -+} -+ -+static int wait_any_alert(int fd, __u32 count, const int *objs, -+ __u32 owner, int alert, __u32 *index) -+{ -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ANY, -+ count, objs, owner, alert, index); -+} -+ -+static int wait_all_alert(int fd, __u32 count, const int *objs, -+ __u32 owner, int alert, __u32 *index) -+{ -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ALL, -+ count, objs, owner, alert, index); - } - - TEST(semaphore_state) -@@ -1095,4 +1110,162 @@ TEST(wake_all) - close(fd); - } - -+TEST(alert_any) -+{ -+ struct ntsync_event_args event_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ __u32 index, count, signaled; -+ int objs[2], fd, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 0; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ objs[0] = sem_args.sem; -+ -+ sem_args.count = 1; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ objs[1] = sem_args.sem; -+ -+ event_args.manual = true; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any_alert(fd, 0, NULL, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any_alert(fd, 0, NULL, 123, event_args.event, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, index); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, index); -+ -+ close(event_args.event); -+ -+ /* test with an auto-reset event */ -+ -+ event_args.manual = false; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ count = 1; -+ ret = post_sem(objs[0], &count); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, index); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ close(event_args.event); -+ -+ close(objs[0]); -+ close(objs[1]); -+ -+ close(fd); -+} -+ -+TEST(alert_all) -+{ -+ struct ntsync_event_args event_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ __u32 index, count, signaled; -+ int objs[2], fd, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 2; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ objs[0] = sem_args.sem; -+ -+ sem_args.count = 1; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ objs[1] = sem_args.sem; -+ -+ event_args.manual = true; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, index); -+ -+ close(event_args.event); -+ -+ /* test with an auto-reset event */ -+ -+ event_args.manual = false; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ count = 2; -+ ret = post_sem(objs[1], &count); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, index); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ close(event_args.event); -+ -+ close(objs[0]); -+ close(objs[1]); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0027-[PATCH_v2_28_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_via_alerts..patch" "b/linux-clang/linux6.8-zen/patches/0027-[PATCH_v2_28_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_via_alerts..patch" deleted file mode 100644 index 5e0734b..0000000 --- "a/linux-clang/linux6.8-zen/patches/0027-[PATCH_v2_28_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_via_alerts..patch" +++ /dev/null @@ -1,110 +0,0 @@ -Expand the alert tests to cover alerting a thread mid-wait, to test that the -relevant scheduling logic works correctly. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 62 +++++++++++++++++++ - 1 file changed, 62 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 5465a16d38b3..968874d7e325 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -1113,9 +1113,12 @@ TEST(wake_all) - TEST(alert_any) - { - struct ntsync_event_args event_args = {0}; -+ struct ntsync_wait_args wait_args = {0}; - struct ntsync_sem_args sem_args = {0}; - __u32 index, count, signaled; -+ struct wait_args thread_args; - int objs[2], fd, ret; -+ pthread_t thread; - - fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); - ASSERT_LE(0, fd); -@@ -1163,6 +1166,34 @@ TEST(alert_any) - EXPECT_EQ(0, ret); - EXPECT_EQ(2, index); - -+ /* test wakeup via alert */ -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.objs = (uintptr_t)objs; -+ wait_args.count = 2; -+ wait_args.owner = 123; -+ wait_args.index = 0xdeadbeef; -+ wait_args.alert = event_args.event; -+ thread_args.fd = fd; -+ thread_args.args = &wait_args; -+ thread_args.request = NTSYNC_IOC_WAIT_ANY; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(2, wait_args.index); -+ - close(event_args.event); - - /* test with an auto-reset event */ -@@ -1199,9 +1230,12 @@ TEST(alert_any) - TEST(alert_all) - { - struct ntsync_event_args event_args = {0}; -+ struct ntsync_wait_args wait_args = {0}; - struct ntsync_sem_args sem_args = {0}; -+ struct wait_args thread_args; - __u32 index, count, signaled; - int objs[2], fd, ret; -+ pthread_t thread; - - fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); - ASSERT_LE(0, fd); -@@ -1235,6 +1269,34 @@ TEST(alert_all) - EXPECT_EQ(0, ret); - EXPECT_EQ(2, index); - -+ /* test wakeup via alert */ -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.objs = (uintptr_t)objs; -+ wait_args.count = 2; -+ wait_args.owner = 123; -+ wait_args.index = 0xdeadbeef; -+ wait_args.alert = event_args.event; -+ thread_args.fd = fd; -+ thread_args.args = &wait_args; -+ thread_args.request = NTSYNC_IOC_WAIT_ALL; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(2, wait_args.index); -+ - close(event_args.event); - - /* test with an auto-reset event */ --- -2.43.0 diff --git "a/linux-clang/linux6.8-zen/patches/0028-[PATCH_v2_29_31]_selftests:_ntsync:_Add_a_stress_test_for\n_contended_waits..patch" "b/linux-clang/linux6.8-zen/patches/0028-[PATCH_v2_29_31]_selftests:_ntsync:_Add_a_stress_test_for\n_contended_waits..patch" deleted file mode 100644 index 5fcc536..0000000 --- "a/linux-clang/linux6.8-zen/patches/0028-[PATCH_v2_29_31]_selftests:_ntsync:_Add_a_stress_test_for\n_contended_waits..patch" +++ /dev/null @@ -1,97 +0,0 @@ -Test a more realistic usage pattern, and one with heavy contention, in order to -actually exercise ntsync's internal synchronization. - -This test has several threads in a tight loop acquiring a mutex, modifying some -shared data, and then releasing the mutex. At the end we check if the data is -consistent. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 74 +++++++++++++++++++ - 1 file changed, 74 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 968874d7e325..5fa2c9a0768c 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -1330,4 +1330,78 @@ TEST(alert_all) - close(fd); - } - -+#define STRESS_LOOPS 10000 -+#define STRESS_THREADS 4 -+ -+static unsigned int stress_counter; -+static int stress_device, stress_start_event, stress_mutex; -+ -+static void *stress_thread(void *arg) -+{ -+ struct ntsync_wait_args wait_args = {0}; -+ __u32 index, count, i; -+ int ret; -+ -+ wait_args.timeout = UINT64_MAX; -+ wait_args.count = 1; -+ wait_args.objs = (uintptr_t)&stress_start_event; -+ wait_args.owner = gettid(); -+ wait_args.index = 0xdeadbeef; -+ -+ ioctl(stress_device, NTSYNC_IOC_WAIT_ANY, &wait_args); -+ -+ wait_args.objs = (uintptr_t)&stress_mutex; -+ -+ for (i = 0; i < STRESS_LOOPS; ++i) { -+ ioctl(stress_device, NTSYNC_IOC_WAIT_ANY, &wait_args); -+ -+ ++stress_counter; -+ -+ unlock_mutex(stress_mutex, wait_args.owner, &count); -+ } -+ -+ return NULL; -+} -+ -+TEST(stress_wait) -+{ -+ struct ntsync_event_args event_args; -+ struct ntsync_mutex_args mutex_args; -+ pthread_t threads[STRESS_THREADS]; -+ __u32 signaled, i; -+ int ret; -+ -+ stress_device = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, stress_device); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 0; -+ ret = ioctl(stress_device, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ stress_mutex = mutex_args.mutex; -+ -+ event_args.manual = 1; -+ event_args.signaled = 0; -+ ret = ioctl(stress_device, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ stress_start_event = event_args.event; -+ -+ for (i = 0; i < STRESS_THREADS; ++i) -+ pthread_create(&threads[i], NULL, stress_thread, NULL); -+ -+ ret = ioctl(stress_start_event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ for (i = 0; i < STRESS_THREADS; ++i) { -+ ret = pthread_join(threads[i], NULL); -+ EXPECT_EQ(0, ret); -+ } -+ -+ EXPECT_EQ(STRESS_LOOPS * STRESS_THREADS, stress_counter); -+ -+ close(stress_start_event); -+ close(stress_mutex); -+ close(stress_device); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/patches/0029-[PATCH_v2_30_31]_maintainers:_Add_an_entry_for_ntsync..patch b/linux-clang/linux6.8-zen/patches/0029-[PATCH_v2_30_31]_maintainers:_Add_an_entry_for_ntsync..patch deleted file mode 100644 index f7e2bd6..0000000 --- a/linux-clang/linux6.8-zen/patches/0029-[PATCH_v2_30_31]_maintainers:_Add_an_entry_for_ntsync..patch +++ /dev/null @@ -1,29 +0,0 @@ -Add myself as maintainer, supported by CodeWeavers. - -Signed-off-by: Elizabeth Figura ---- - MAINTAINERS | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/MAINTAINERS b/MAINTAINERS -index 9ed4d3868539..d83dd35d9f73 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -15595,6 +15595,15 @@ T: git https://github.com/Paragon-Software-Group/linux-ntfs3.git - F: Documentation/filesystems/ntfs3.rst - F: fs/ntfs3/ - -+NTSYNC SYNCHRONIZATION PRIMITIVE DRIVER -+M: Elizabeth Figura -+L: wine-devel@winehq.org -+S: Supported -+F: Documentation/userspace-api/ntsync.rst -+F: drivers/misc/ntsync.c -+F: include/uapi/linux/ntsync.h -+F: tools/testing/selftests/drivers/ntsync/ -+ - NUBUS SUBSYSTEM - M: Finn Thain - L: linux-m68k@lists.linux-m68k.org --- -2.43.0 diff --git a/linux-clang/linux6.8-zen/template b/linux-clang/linux6.8-zen/template index d4af856..bbf4fdc 100644 --- a/linux-clang/linux6.8-zen/template +++ b/linux-clang/linux6.8-zen/template @@ -1,5 +1,5 @@ pkgname=linux6.8-zen -version=6.8.6 +version=6.8.7 revision=1 zen=1 wrksrc="linux-${version}-zen${zen}" @@ -8,7 +8,7 @@ maintainer="Wizzard " license="GPL-2.0-only" homepage="http://www.zen-kernel.org/" distfiles="https://github.com/zen-kernel/zen-kernel/archive/refs/tags/v${version}-zen${zen}.tar.gz" -checksum="a6f2cd6b3ed6555161b688d41d04275c2bf05e893778a8e5b2c52a3ff627db1f" +checksum="5ab6ad1d26925f02a74b41d485e5faf25056efec123d0a1433aa3a4108534aae" python_version=3 patch_args="-Np1" diff --git "a/linux-gcc/linux6.8-zen/patches/0000-[PATCH_v2_1_31]_ntsync:_Introduce_the_ntsync_driver_and_character\n_device..patch" "b/linux-gcc/linux6.8-zen/patches/0000-[PATCH_v2_1_31]_ntsync:_Introduce_the_ntsync_driver_and_character\n_device..patch" deleted file mode 100644 index 5193a8c..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0000-[PATCH_v2_1_31]_ntsync:_Introduce_the_ntsync_driver_and_character\n_device..patch" +++ /dev/null @@ -1,107 +0,0 @@ -ntsync uses a misc device as the simplest and least intrusive uAPI interface. - -Each file description on the device represents an isolated NT instance, intended -to correspond to a single NT virtual machine. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/Kconfig | 11 +++++++++ - drivers/misc/Makefile | 1 + - drivers/misc/ntsync.c | 52 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 64 insertions(+) - create mode 100644 drivers/misc/ntsync.c - -diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index 4fb291f0bf7c..801ed229ed7d 100644 ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -506,6 +506,17 @@ config OPEN_DICE - - If unsure, say N. - -+config NTSYNC -+ tristate "NT synchronization primitive emulation" -+ help -+ This module provides kernel support for emulation of Windows NT -+ synchronization primitives. It is not a hardware driver. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called ntsync. -+ -+ If unsure, say N. -+ - config VCPU_STALL_DETECTOR - tristate "Guest vCPU stall detector" - depends on OF && HAS_IOMEM -diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index ea6ea5bbbc9c..153a3f4837e8 100644 ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -59,6 +59,7 @@ obj-$(CONFIG_PVPANIC) += pvpanic/ - obj-$(CONFIG_UACCE) += uacce/ - obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o - obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o -+obj-$(CONFIG_NTSYNC) += ntsync.o - obj-$(CONFIG_HI6421V600_IRQ) += hi6421v600-irq.o - obj-$(CONFIG_OPEN_DICE) += open-dice.o - obj-$(CONFIG_GP_PCI1XXXX) += mchp_pci1xxxx/ -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -new file mode 100644 -index 000000000000..bd76e653d83e ---- /dev/null -+++ b/drivers/misc/ntsync.c -@@ -0,0 +1,52 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * ntsync.c - Kernel driver for NT synchronization primitives -+ * -+ * Copyright (C) 2024 Elizabeth Figura -+ */ -+ -+#include -+#include -+#include -+ -+#define NTSYNC_NAME "ntsync" -+ -+static int ntsync_char_open(struct inode *inode, struct file *file) -+{ -+ return nonseekable_open(inode, file); -+} -+ -+static int ntsync_char_release(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+static long ntsync_char_ioctl(struct file *file, unsigned int cmd, -+ unsigned long parm) -+{ -+ switch (cmd) { -+ default: -+ return -ENOIOCTLCMD; -+ } -+} -+ -+static const struct file_operations ntsync_fops = { -+ .owner = THIS_MODULE, -+ .open = ntsync_char_open, -+ .release = ntsync_char_release, -+ .unlocked_ioctl = ntsync_char_ioctl, -+ .compat_ioctl = compat_ptr_ioctl, -+ .llseek = no_llseek, -+}; -+ -+static struct miscdevice ntsync_misc = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = NTSYNC_NAME, -+ .fops = &ntsync_fops, -+}; -+ -+module_misc_device(ntsync_misc); -+ -+MODULE_AUTHOR("Elizabeth Figura "); -+MODULE_DESCRIPTION("Kernel driver for NT synchronization primitives"); -+MODULE_LICENSE("GPL"); --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0001-[PATCH_v2_2_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_SEM..patch b/linux-gcc/linux6.8-zen/patches/0001-[PATCH_v2_2_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_SEM..patch deleted file mode 100644 index 6d223a2..0000000 --- a/linux-gcc/linux6.8-zen/patches/0001-[PATCH_v2_2_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_SEM..patch +++ /dev/null @@ -1,228 +0,0 @@ -This corresponds to the NT syscall NtCreateSemaphore(). - -Semaphores are one of three types of object to be implemented in this driver, -the others being mutexes and events. - -An NT semaphore contains a 32-bit counter, and is signaled and can be acquired -when the counter is nonzero. The counter has a maximum value which is specified -at creation time. The initial value of the semaphore is also specified at -creation time. There are no restrictions on the maximum and initial value. - -Each object is exposed as an file, to which any number of fds may be opened. -When all fds are closed, the object is deleted. - -Objects hold a pointer to the ntsync_device that created them. The device's -reference count is driven by struct file. - -Signed-off-by: Elizabeth Figura ---- - .../userspace-api/ioctl/ioctl-number.rst | 2 + - drivers/misc/ntsync.c | 131 ++++++++++++++++++ - include/uapi/linux/ntsync.h | 21 +++ - 3 files changed, 154 insertions(+) - create mode 100644 include/uapi/linux/ntsync.h - -diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst -index 457e16f06e04..2f5c6994f042 100644 ---- a/Documentation/userspace-api/ioctl/ioctl-number.rst -+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst -@@ -173,6 +173,8 @@ Code Seq# Include File Comments - 'M' 00-0F drivers/video/fsl-diu-fb.h conflict! - 'N' 00-1F drivers/usb/scanner.h - 'N' 40-7F drivers/block/nvme.c -+'N' 80-8F uapi/linux/ntsync.h NT synchronization primitives -+ - 'O' 00-06 mtd/ubi-user.h UBI - 'P' all linux/soundcard.h conflict! - 'P' 60-6F sound/sscape_ioctl.h conflict! -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index bd76e653d83e..20158ec148bc 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -5,26 +5,157 @@ - * Copyright (C) 2024 Elizabeth Figura - */ - -+#include -+#include - #include - #include - #include -+#include -+#include - - #define NTSYNC_NAME "ntsync" - -+enum ntsync_type { -+ NTSYNC_TYPE_SEM, -+}; -+ -+/* -+ * Individual synchronization primitives are represented by -+ * struct ntsync_obj, and each primitive is backed by a file. -+ * -+ * The whole namespace is represented by a struct ntsync_device also -+ * backed by a file. -+ * -+ * Both rely on struct file for reference counting. Individual -+ * ntsync_obj objects take a reference to the device when created. -+ */ -+ -+struct ntsync_obj { -+ enum ntsync_type type; -+ -+ union { -+ struct { -+ __u32 count; -+ __u32 max; -+ } sem; -+ } u; -+ -+ struct file *file; -+ struct ntsync_device *dev; -+}; -+ -+struct ntsync_device { -+ struct file *file; -+}; -+ -+static int ntsync_obj_release(struct inode *inode, struct file *file) -+{ -+ struct ntsync_obj *obj = file->private_data; -+ -+ fput(obj->dev->file); -+ kfree(obj); -+ -+ return 0; -+} -+ -+static const struct file_operations ntsync_obj_fops = { -+ .owner = THIS_MODULE, -+ .release = ntsync_obj_release, -+ .llseek = no_llseek, -+}; -+ -+static struct ntsync_obj *ntsync_alloc_obj(struct ntsync_device *dev, -+ enum ntsync_type type) -+{ -+ struct ntsync_obj *obj; -+ -+ obj = kzalloc(sizeof(*obj), GFP_KERNEL); -+ if (!obj) -+ return NULL; -+ obj->type = type; -+ obj->dev = dev; -+ get_file(dev->file); -+ -+ return obj; -+} -+ -+static int ntsync_obj_get_fd(struct ntsync_obj *obj) -+{ -+ struct file *file; -+ int fd; -+ -+ fd = get_unused_fd_flags(O_CLOEXEC); -+ if (fd < 0) -+ return fd; -+ file = anon_inode_getfile("ntsync", &ntsync_obj_fops, obj, O_RDWR); -+ if (IS_ERR(file)) { -+ put_unused_fd(fd); -+ return PTR_ERR(file); -+ } -+ obj->file = file; -+ fd_install(fd, file); -+ -+ return fd; -+} -+ -+static int ntsync_create_sem(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_sem_args __user *user_args = argp; -+ struct ntsync_sem_args args; -+ struct ntsync_obj *sem; -+ int fd; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ if (args.count > args.max) -+ return -EINVAL; -+ -+ sem = ntsync_alloc_obj(dev, NTSYNC_TYPE_SEM); -+ if (!sem) -+ return -ENOMEM; -+ sem->u.sem.count = args.count; -+ sem->u.sem.max = args.max; -+ fd = ntsync_obj_get_fd(sem); -+ if (fd < 0) { -+ kfree(sem); -+ return fd; -+ } -+ -+ return put_user(fd, &user_args->sem); -+} -+ - static int ntsync_char_open(struct inode *inode, struct file *file) - { -+ struct ntsync_device *dev; -+ -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); -+ if (!dev) -+ return -ENOMEM; -+ -+ file->private_data = dev; -+ dev->file = file; - return nonseekable_open(inode, file); - } - - static int ntsync_char_release(struct inode *inode, struct file *file) - { -+ struct ntsync_device *dev = file->private_data; -+ -+ kfree(dev); -+ - return 0; - } - - static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - unsigned long parm) - { -+ struct ntsync_device *dev = file->private_data; -+ void __user *argp = (void __user *)parm; -+ - switch (cmd) { -+ case NTSYNC_IOC_CREATE_SEM: -+ return ntsync_create_sem(dev, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -new file mode 100644 -index 000000000000..6a4867a6c97b ---- /dev/null -+++ b/include/uapi/linux/ntsync.h -@@ -0,0 +1,21 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * Kernel support for NT synchronization primitive emulation -+ * -+ * Copyright (C) 2021-2022 Elizabeth Figura -+ */ -+ -+#ifndef __LINUX_NTSYNC_H -+#define __LINUX_NTSYNC_H -+ -+#include -+ -+struct ntsync_sem_args { -+ __u32 sem; -+ __u32 count; -+ __u32 max; -+}; -+ -+#define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) -+ -+#endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0002-[PATCH_v2_3_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_POST..patch b/linux-gcc/linux6.8-zen/patches/0002-[PATCH_v2_3_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_POST..patch deleted file mode 100644 index 78fdffc..0000000 --- a/linux-gcc/linux6.8-zen/patches/0002-[PATCH_v2_3_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_POST..patch +++ /dev/null @@ -1,147 +0,0 @@ -This corresponds to the NT syscall NtReleaseSemaphore(). - -This increases the semaphore's internal counter by the given value, and returns -the previous value. If the counter would overflow the defined maximum, the -function instead fails and returns -EOVERFLOW. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 72 +++++++++++++++++++++++++++++++++++-- - include/uapi/linux/ntsync.h | 2 ++ - 2 files changed, 71 insertions(+), 3 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 20158ec148bc..3c2f743c58b0 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -10,7 +10,9 @@ - #include - #include - #include -+#include - #include -+#include - #include - - #define NTSYNC_NAME "ntsync" -@@ -31,23 +33,70 @@ enum ntsync_type { - */ - - struct ntsync_obj { -+ spinlock_t lock; -+ - enum ntsync_type type; - -+ struct file *file; -+ struct ntsync_device *dev; -+ -+ /* The following fields are protected by the object lock. */ - union { - struct { - __u32 count; - __u32 max; - } sem; - } u; -- -- struct file *file; -- struct ntsync_device *dev; - }; - - struct ntsync_device { - struct file *file; - }; - -+/* -+ * Actually change the semaphore state, returning -EOVERFLOW if it is made -+ * invalid. -+ */ -+static int post_sem_state(struct ntsync_obj *sem, __u32 count) -+{ -+ __u32 sum; -+ -+ lockdep_assert_held(&sem->lock); -+ -+ if (check_add_overflow(sem->u.sem.count, count, &sum) || -+ sum > sem->u.sem.max) -+ return -EOVERFLOW; -+ -+ sem->u.sem.count = sum; -+ return 0; -+} -+ -+static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) -+{ -+ __u32 __user *user_args = argp; -+ __u32 prev_count; -+ __u32 args; -+ int ret; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ if (sem->type != NTSYNC_TYPE_SEM) -+ return -EINVAL; -+ -+ spin_lock(&sem->lock); -+ -+ prev_count = sem->u.sem.count; -+ ret = post_sem_state(sem, args); -+ -+ spin_unlock(&sem->lock); -+ -+ if (!ret && put_user(prev_count, user_args)) -+ ret = -EFAULT; -+ -+ return ret; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -58,9 +107,25 @@ static int ntsync_obj_release(struct inode *inode, struct file *file) - return 0; - } - -+static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, -+ unsigned long parm) -+{ -+ struct ntsync_obj *obj = file->private_data; -+ void __user *argp = (void __user *)parm; -+ -+ switch (cmd) { -+ case NTSYNC_IOC_SEM_POST: -+ return ntsync_sem_post(obj, argp); -+ default: -+ return -ENOIOCTLCMD; -+ } -+} -+ - static const struct file_operations ntsync_obj_fops = { - .owner = THIS_MODULE, - .release = ntsync_obj_release, -+ .unlocked_ioctl = ntsync_obj_ioctl, -+ .compat_ioctl = compat_ptr_ioctl, - .llseek = no_llseek, - }; - -@@ -75,6 +140,7 @@ static struct ntsync_obj *ntsync_alloc_obj(struct ntsync_device *dev, - obj->type = type; - obj->dev = dev; - get_file(dev->file); -+ spin_lock_init(&obj->lock); - - return obj; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 6a4867a6c97b..dcfa38fdc93c 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -18,4 +18,6 @@ struct ntsync_sem_args { - - #define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) - -+#define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) -+ - #endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0003-[PATCH_v2_4_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ANY..patch b/linux-gcc/linux6.8-zen/patches/0003-[PATCH_v2_4_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ANY..patch deleted file mode 100644 index 6d57657..0000000 --- a/linux-gcc/linux6.8-zen/patches/0003-[PATCH_v2_4_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ANY..patch +++ /dev/null @@ -1,360 +0,0 @@ -This corresponds to part of the functionality of the NT syscall -NtWaitForMultipleObjects(). Specifically, it implements the behaviour where -the third argument (wait_any) is TRUE, and it does not handle alertable waits. -Those features have been split out into separate patches to ease review. - -NTSYNC_IOC_WAIT_ANY is a vectored wait function similar to poll(). Unlike -poll(), it "consumes" objects when they are signaled. For semaphores, this means -decreasing one from the internal counter. At most one object can be consumed by -this function. - -Up to 64 objects can be waited on at once. As soon as one is signaled, the -object with the lowest index is consumed, and that index is returned via the -"index" field. - -A timeout is supported. The timeout is passed as a u64 nanosecond value, which -represents absolute time measured against the MONOTONIC clock. If U64_MAX is -passed, the ioctl waits indefinitely. - -This ioctl validates that all objects belong to the relevant device. This is not -necessary for any technical reason related to NTSYNC_IOC_WAIT_ANY, but will be -necessary for NTSYNC_IOC_WAIT_ALL introduced in the following patch. - -Wait ioctls need to take a temporary reference to each object being waited on. -As with the device, the reference count of struct file is used for ntsync_obj. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 239 ++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 12 ++ - 2 files changed, 251 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 3c2f743c58b0..ad93ca0f8b84 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -6,11 +6,16 @@ - */ - - #include -+#include - #include - #include -+#include -+#include - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -30,6 +35,8 @@ enum ntsync_type { - * - * Both rely on struct file for reference counting. Individual - * ntsync_obj objects take a reference to the device when created. -+ * Wait operations take a reference to each object being waited on for -+ * the duration of the wait. - */ - - struct ntsync_obj { -@@ -47,12 +54,55 @@ struct ntsync_obj { - __u32 max; - } sem; - } u; -+ -+ struct list_head any_waiters; -+}; -+ -+struct ntsync_q_entry { -+ struct list_head node; -+ struct ntsync_q *q; -+ struct ntsync_obj *obj; -+ __u32 index; -+}; -+ -+struct ntsync_q { -+ struct task_struct *task; -+ __u32 owner; -+ -+ /* -+ * Protected via atomic_cmpxchg(). Only the thread that wins the -+ * compare-and-swap may actually change object states and wake this -+ * task. -+ */ -+ atomic_t signaled; -+ -+ __u32 count; -+ struct ntsync_q_entry entries[]; - }; - - struct ntsync_device { - struct file *file; - }; - -+static void try_wake_any_sem(struct ntsync_obj *sem) -+{ -+ struct ntsync_q_entry *entry; -+ -+ lockdep_assert_held(&sem->lock); -+ -+ list_for_each_entry(entry, &sem->any_waiters, node) { -+ struct ntsync_q *q = entry->q; -+ -+ if (!sem->u.sem.count) -+ break; -+ -+ if (atomic_cmpxchg(&q->signaled, -1, entry->index) == -1) { -+ sem->u.sem.count--; -+ wake_up_process(q->task); -+ } -+ } -+} -+ - /* - * Actually change the semaphore state, returning -EOVERFLOW if it is made - * invalid. -@@ -88,6 +138,8 @@ static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) - - prev_count = sem->u.sem.count; - ret = post_sem_state(sem, args); -+ if (!ret) -+ try_wake_any_sem(sem); - - spin_unlock(&sem->lock); - -@@ -141,6 +193,7 @@ static struct ntsync_obj *ntsync_alloc_obj(struct ntsync_device *dev, - obj->dev = dev; - get_file(dev->file); - spin_lock_init(&obj->lock); -+ INIT_LIST_HEAD(&obj->any_waiters); - - return obj; - } -@@ -191,6 +244,190 @@ static int ntsync_create_sem(struct ntsync_device *dev, void __user *argp) - return put_user(fd, &user_args->sem); - } - -+static struct ntsync_obj *get_obj(struct ntsync_device *dev, int fd) -+{ -+ struct file *file = fget(fd); -+ struct ntsync_obj *obj; -+ -+ if (file->f_op != &ntsync_obj_fops) { -+ fput(file); -+ return NULL; -+ } -+ -+ obj = file->private_data; -+ if (obj->dev != dev) { -+ fput(file); -+ return NULL; -+ } -+ -+ return obj; -+} -+ -+static void put_obj(struct ntsync_obj *obj) -+{ -+ fput(obj->file); -+} -+ -+static int ntsync_schedule(const struct ntsync_q *q, const struct ntsync_wait_args *args) -+{ -+ ktime_t timeout = ns_to_ktime(args->timeout); -+ ktime_t *timeout_ptr; -+ int ret = 0; -+ -+ timeout_ptr = (args->timeout == U64_MAX ? NULL : &timeout); -+ -+ do { -+ if (signal_pending(current)) { -+ ret = -ERESTARTSYS; -+ break; -+ } -+ -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (atomic_read(&q->signaled) != -1) { -+ ret = 0; -+ break; -+ } -+ ret = schedule_hrtimeout(timeout_ptr, HRTIMER_MODE_ABS); -+ } while (ret < 0); -+ __set_current_state(TASK_RUNNING); -+ -+ return ret; -+} -+ -+/* -+ * Allocate and initialize the ntsync_q structure, but do not queue us yet. -+ */ -+static int setup_wait(struct ntsync_device *dev, -+ const struct ntsync_wait_args *args, -+ struct ntsync_q **ret_q) -+{ -+ const __u32 count = args->count; -+ int fds[NTSYNC_MAX_WAIT_COUNT]; -+ struct ntsync_q *q; -+ __u32 i, j; -+ -+ if (!args->owner || args->pad) -+ return -EINVAL; -+ -+ if (args->count > NTSYNC_MAX_WAIT_COUNT) -+ return -EINVAL; -+ -+ if (copy_from_user(fds, u64_to_user_ptr(args->objs), -+ array_size(count, sizeof(*fds)))) -+ return -EFAULT; -+ -+ q = kmalloc(struct_size(q, entries, count), GFP_KERNEL); -+ if (!q) -+ return -ENOMEM; -+ q->task = current; -+ q->owner = args->owner; -+ atomic_set(&q->signaled, -1); -+ q->count = count; -+ -+ for (i = 0; i < count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = get_obj(dev, fds[i]); -+ -+ if (!obj) -+ goto err; -+ -+ entry->obj = obj; -+ entry->q = q; -+ entry->index = i; -+ } -+ -+ *ret_q = q; -+ return 0; -+ -+err: -+ for (j = 0; j < i; j++) -+ put_obj(q->entries[j].obj); -+ kfree(q); -+ return -EINVAL; -+} -+ -+static void try_wake_any_obj(struct ntsync_obj *obj) -+{ -+ switch (obj->type) { -+ case NTSYNC_TYPE_SEM: -+ try_wake_any_sem(obj); -+ break; -+ } -+} -+ -+static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_wait_args args; -+ struct ntsync_q *q; -+ int signaled; -+ __u32 i; -+ int ret; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ ret = setup_wait(dev, &args, &q); -+ if (ret < 0) -+ return ret; -+ -+ /* queue ourselves */ -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ spin_lock(&obj->lock); -+ list_add_tail(&entry->node, &obj->any_waiters); -+ spin_unlock(&obj->lock); -+ } -+ -+ /* check if we are already signaled */ -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_obj *obj = q->entries[i].obj; -+ -+ if (atomic_read(&q->signaled) != -1) -+ break; -+ -+ spin_lock(&obj->lock); -+ try_wake_any_obj(obj); -+ spin_unlock(&obj->lock); -+ } -+ -+ /* sleep */ -+ -+ ret = ntsync_schedule(q, &args); -+ -+ /* and finally, unqueue */ -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ spin_lock(&obj->lock); -+ list_del(&entry->node); -+ spin_unlock(&obj->lock); -+ -+ put_obj(obj); -+ } -+ -+ signaled = atomic_read(&q->signaled); -+ if (signaled != -1) { -+ struct ntsync_wait_args __user *user_args = argp; -+ -+ /* even if we caught a signal, we need to communicate success */ -+ ret = 0; -+ -+ if (put_user(signaled, &user_args->index)) -+ ret = -EFAULT; -+ } else if (!ret) { -+ ret = -ETIMEDOUT; -+ } -+ -+ kfree(q); -+ return ret; -+} -+ - static int ntsync_char_open(struct inode *inode, struct file *file) - { - struct ntsync_device *dev; -@@ -222,6 +459,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - switch (cmd) { - case NTSYNC_IOC_CREATE_SEM: - return ntsync_create_sem(dev, argp); -+ case NTSYNC_IOC_WAIT_ANY: -+ return ntsync_wait_any(dev, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index dcfa38fdc93c..56b643fab611 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -16,7 +16,19 @@ struct ntsync_sem_args { - __u32 max; - }; - -+struct ntsync_wait_args { -+ __u64 timeout; -+ __u64 objs; -+ __u32 count; -+ __u32 owner; -+ __u32 index; -+ __u32 pad; -+}; -+ -+#define NTSYNC_MAX_WAIT_COUNT 64 -+ - #define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) -+#define NTSYNC_IOC_WAIT_ANY _IOWR('N', 0x82, struct ntsync_wait_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0004-[PATCH_v2_5_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ALL..patch b/linux-gcc/linux6.8-zen/patches/0004-[PATCH_v2_5_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ALL..patch deleted file mode 100644 index 7d2c890..0000000 --- a/linux-gcc/linux6.8-zen/patches/0004-[PATCH_v2_5_31]_ntsync:_Introduce_NTSYNC_IOC_WAIT_ALL..patch +++ /dev/null @@ -1,365 +0,0 @@ -This is similar to NTSYNC_IOC_WAIT_ANY, but waits until all of the objects are -simultaneously signaled, and then acquires all of them as a single atomic -operation. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 242 ++++++++++++++++++++++++++++++++++-- - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 235 insertions(+), 8 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index ad93ca0f8b84..d5759e9a3a8e 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -55,7 +55,34 @@ struct ntsync_obj { - } sem; - } u; - -+ /* -+ * any_waiters is protected by the object lock, but all_waiters is -+ * protected by the device wait_all_lock. -+ */ - struct list_head any_waiters; -+ struct list_head all_waiters; -+ -+ /* -+ * Hint describing how many tasks are queued on this object in a -+ * wait-all operation. -+ * -+ * Any time we do a wake, we may need to wake "all" waiters as well as -+ * "any" waiters. In order to atomically wake "all" waiters, we must -+ * lock all of the objects, and that means grabbing the wait_all_lock -+ * below (and, due to lock ordering rules, before locking this object). -+ * However, wait-all is a rare operation, and grabbing the wait-all -+ * lock for every wake would create unnecessary contention. -+ * Therefore we first check whether all_hint is zero, and, if it is, -+ * we skip trying to wake "all" waiters. -+ * -+ * This hint isn't protected by any lock. It might change during the -+ * course of a wake, but there's no meaningful race there; it's only a -+ * hint. -+ * -+ * Since wait requests must originate from user-space threads, we're -+ * limited here by PID_MAX_LIMIT, so there's no risk of overflow. -+ */ -+ atomic_t all_hint; - }; - - struct ntsync_q_entry { -@@ -76,14 +103,99 @@ struct ntsync_q { - */ - atomic_t signaled; - -+ bool all; - __u32 count; - struct ntsync_q_entry entries[]; - }; - - struct ntsync_device { -+ /* -+ * Wait-all operations must atomically grab all objects, and be totally -+ * ordered with respect to each other and wait-any operations. -+ * If one thread is trying to acquire several objects, another thread -+ * cannot touch the object at the same time. -+ * -+ * We achieve this by grabbing multiple object locks at the same time. -+ * However, this creates a lock ordering problem. To solve that problem, -+ * wait_all_lock is taken first whenever multiple objects must be locked -+ * at the same time. -+ */ -+ spinlock_t wait_all_lock; -+ - struct file *file; - }; - -+static bool is_signaled(struct ntsync_obj *obj, __u32 owner) -+{ -+ lockdep_assert_held(&obj->lock); -+ -+ switch (obj->type) { -+ case NTSYNC_TYPE_SEM: -+ return !!obj->u.sem.count; -+ } -+ -+ WARN(1, "bad object type %#x\n", obj->type); -+ return false; -+} -+ -+/* -+ * "locked_obj" is an optional pointer to an object which is already locked and -+ * should not be locked again. This is necessary so that changing an object's -+ * state and waking it can be a single atomic operation. -+ */ -+static void try_wake_all(struct ntsync_device *dev, struct ntsync_q *q, -+ struct ntsync_obj *locked_obj) -+{ -+ __u32 count = q->count; -+ bool can_wake = true; -+ __u32 i; -+ -+ lockdep_assert_held(&dev->wait_all_lock); -+ if (locked_obj) -+ lockdep_assert_held(&locked_obj->lock); -+ -+ for (i = 0; i < count; i++) { -+ if (q->entries[i].obj != locked_obj) -+ spin_lock_nest_lock(&q->entries[i].obj->lock, &dev->wait_all_lock); -+ } -+ -+ for (i = 0; i < count; i++) { -+ if (!is_signaled(q->entries[i].obj, q->owner)) { -+ can_wake = false; -+ break; -+ } -+ } -+ -+ if (can_wake && atomic_cmpxchg(&q->signaled, -1, 0) == -1) { -+ for (i = 0; i < count; i++) { -+ struct ntsync_obj *obj = q->entries[i].obj; -+ -+ switch (obj->type) { -+ case NTSYNC_TYPE_SEM: -+ obj->u.sem.count--; -+ break; -+ } -+ } -+ wake_up_process(q->task); -+ } -+ -+ for (i = 0; i < count; i++) { -+ if (q->entries[i].obj != locked_obj) -+ spin_unlock(&q->entries[i].obj->lock); -+ } -+} -+ -+static void try_wake_all_obj(struct ntsync_device *dev, struct ntsync_obj *obj) -+{ -+ struct ntsync_q_entry *entry; -+ -+ lockdep_assert_held(&dev->wait_all_lock); -+ lockdep_assert_held(&obj->lock); -+ -+ list_for_each_entry(entry, &obj->all_waiters, node) -+ try_wake_all(dev, entry->q, obj); -+} -+ - static void try_wake_any_sem(struct ntsync_obj *sem) - { - struct ntsync_q_entry *entry; -@@ -123,6 +235,7 @@ static int post_sem_state(struct ntsync_obj *sem, __u32 count) - - static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) - { -+ struct ntsync_device *dev = sem->dev; - __u32 __user *user_args = argp; - __u32 prev_count; - __u32 args; -@@ -134,14 +247,29 @@ static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) - if (sem->type != NTSYNC_TYPE_SEM) - return -EINVAL; - -- spin_lock(&sem->lock); -+ if (atomic_read(&sem->all_hint) > 0) { -+ spin_lock(&dev->wait_all_lock); -+ spin_lock_nest_lock(&sem->lock, &dev->wait_all_lock); - -- prev_count = sem->u.sem.count; -- ret = post_sem_state(sem, args); -- if (!ret) -- try_wake_any_sem(sem); -+ prev_count = sem->u.sem.count; -+ ret = post_sem_state(sem, args); -+ if (!ret) { -+ try_wake_all_obj(dev, sem); -+ try_wake_any_sem(sem); -+ } - -- spin_unlock(&sem->lock); -+ spin_unlock(&sem->lock); -+ spin_unlock(&dev->wait_all_lock); -+ } else { -+ spin_lock(&sem->lock); -+ -+ prev_count = sem->u.sem.count; -+ ret = post_sem_state(sem, args); -+ if (!ret) -+ try_wake_any_sem(sem); -+ -+ spin_unlock(&sem->lock); -+ } - - if (!ret && put_user(prev_count, user_args)) - ret = -EFAULT; -@@ -194,6 +322,8 @@ static struct ntsync_obj *ntsync_alloc_obj(struct ntsync_device *dev, - get_file(dev->file); - spin_lock_init(&obj->lock); - INIT_LIST_HEAD(&obj->any_waiters); -+ INIT_LIST_HEAD(&obj->all_waiters); -+ atomic_set(&obj->all_hint, 0); - - return obj; - } -@@ -298,7 +428,7 @@ static int ntsync_schedule(const struct ntsync_q *q, const struct ntsync_wait_ar - * Allocate and initialize the ntsync_q structure, but do not queue us yet. - */ - static int setup_wait(struct ntsync_device *dev, -- const struct ntsync_wait_args *args, -+ const struct ntsync_wait_args *args, bool all, - struct ntsync_q **ret_q) - { - const __u32 count = args->count; -@@ -322,6 +452,7 @@ static int setup_wait(struct ntsync_device *dev, - q->task = current; - q->owner = args->owner; - atomic_set(&q->signaled, -1); -+ q->all = all; - q->count = count; - - for (i = 0; i < count; i++) { -@@ -331,6 +462,16 @@ static int setup_wait(struct ntsync_device *dev, - if (!obj) - goto err; - -+ if (all) { -+ /* Check that the objects are all distinct. */ -+ for (j = 0; j < i; j++) { -+ if (obj == q->entries[j].obj) { -+ put_obj(obj); -+ goto err; -+ } -+ } -+ } -+ - entry->obj = obj; - entry->q = q; - entry->index = i; -@@ -366,7 +507,7 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - if (copy_from_user(&args, argp, sizeof(args))) - return -EFAULT; - -- ret = setup_wait(dev, &args, &q); -+ ret = setup_wait(dev, &args, false, &q); - if (ret < 0) - return ret; - -@@ -428,6 +569,87 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - return ret; - } - -+static int ntsync_wait_all(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_wait_args args; -+ struct ntsync_q *q; -+ int signaled; -+ __u32 i; -+ int ret; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ ret = setup_wait(dev, &args, true, &q); -+ if (ret < 0) -+ return ret; -+ -+ /* queue ourselves */ -+ -+ spin_lock(&dev->wait_all_lock); -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ atomic_inc(&obj->all_hint); -+ -+ /* -+ * obj->all_waiters is protected by dev->wait_all_lock rather -+ * than obj->lock, so there is no need to acquire obj->lock -+ * here. -+ */ -+ list_add_tail(&entry->node, &obj->all_waiters); -+ } -+ -+ /* check if we are already signaled */ -+ -+ try_wake_all(dev, q, NULL); -+ -+ spin_unlock(&dev->wait_all_lock); -+ -+ /* sleep */ -+ -+ ret = ntsync_schedule(q, &args); -+ -+ /* and finally, unqueue */ -+ -+ spin_lock(&dev->wait_all_lock); -+ -+ for (i = 0; i < args.count; i++) { -+ struct ntsync_q_entry *entry = &q->entries[i]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ /* -+ * obj->all_waiters is protected by dev->wait_all_lock rather -+ * than obj->lock, so there is no need to acquire it here. -+ */ -+ list_del(&entry->node); -+ -+ atomic_dec(&obj->all_hint); -+ -+ put_obj(obj); -+ } -+ -+ spin_unlock(&dev->wait_all_lock); -+ -+ signaled = atomic_read(&q->signaled); -+ if (signaled != -1) { -+ struct ntsync_wait_args __user *user_args = argp; -+ -+ /* even if we caught a signal, we need to communicate success */ -+ ret = 0; -+ -+ if (put_user(signaled, &user_args->index)) -+ ret = -EFAULT; -+ } else if (!ret) { -+ ret = -ETIMEDOUT; -+ } -+ -+ kfree(q); -+ return ret; -+} -+ - static int ntsync_char_open(struct inode *inode, struct file *file) - { - struct ntsync_device *dev; -@@ -436,6 +658,8 @@ static int ntsync_char_open(struct inode *inode, struct file *file) - if (!dev) - return -ENOMEM; - -+ spin_lock_init(&dev->wait_all_lock); -+ - file->private_data = dev; - dev->file = file; - return nonseekable_open(inode, file); -@@ -459,6 +683,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - switch (cmd) { - case NTSYNC_IOC_CREATE_SEM: - return ntsync_create_sem(dev, argp); -+ case NTSYNC_IOC_WAIT_ALL: -+ return ntsync_wait_all(dev, argp); - case NTSYNC_IOC_WAIT_ANY: - return ntsync_wait_any(dev, argp); - default: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 56b643fab611..19c37e27a4f8 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -29,6 +29,7 @@ struct ntsync_wait_args { - - #define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) - #define NTSYNC_IOC_WAIT_ANY _IOWR('N', 0x82, struct ntsync_wait_args) -+#define NTSYNC_IOC_WAIT_ALL _IOWR('N', 0x83, struct ntsync_wait_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0005-[PATCH_v2_6_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_MUTEX..patch b/linux-gcc/linux6.8-zen/patches/0005-[PATCH_v2_6_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_MUTEX..patch deleted file mode 100644 index cfd07ce..0000000 --- a/linux-gcc/linux6.8-zen/patches/0005-[PATCH_v2_6_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_MUTEX..patch +++ /dev/null @@ -1,172 +0,0 @@ -This corresponds to the NT syscall NtCreateMutant(). - -An NT mutex is recursive, with a 32-bit recursion counter. When acquired via -NtWaitForMultipleObjects(), the recursion counter is incremented by one. - -The OS records the thread which acquired it. However, in order to keep this -driver self-contained, the owning thread ID is managed by user-space, and passed -as a parameter to all relevant ioctls. - -The initial owner and recursion count, if any, are specified when the mutex is -created. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 67 +++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 7 ++++ - 2 files changed, 74 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index d5759e9a3a8e..6f7086d0440a 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -24,6 +24,7 @@ - - enum ntsync_type { - NTSYNC_TYPE_SEM, -+ NTSYNC_TYPE_MUTEX, - }; - - /* -@@ -53,6 +54,10 @@ struct ntsync_obj { - __u32 count; - __u32 max; - } sem; -+ struct { -+ __u32 count; -+ __u32 owner; -+ } mutex; - } u; - - /* -@@ -132,6 +137,10 @@ static bool is_signaled(struct ntsync_obj *obj, __u32 owner) - switch (obj->type) { - case NTSYNC_TYPE_SEM: - return !!obj->u.sem.count; -+ case NTSYNC_TYPE_MUTEX: -+ if (obj->u.mutex.owner && obj->u.mutex.owner != owner) -+ return false; -+ return obj->u.mutex.count < UINT_MAX; - } - - WARN(1, "bad object type %#x\n", obj->type); -@@ -174,6 +183,10 @@ static void try_wake_all(struct ntsync_device *dev, struct ntsync_q *q, - case NTSYNC_TYPE_SEM: - obj->u.sem.count--; - break; -+ case NTSYNC_TYPE_MUTEX: -+ obj->u.mutex.count++; -+ obj->u.mutex.owner = q->owner; -+ break; - } - } - wake_up_process(q->task); -@@ -215,6 +228,28 @@ static void try_wake_any_sem(struct ntsync_obj *sem) - } - } - -+static void try_wake_any_mutex(struct ntsync_obj *mutex) -+{ -+ struct ntsync_q_entry *entry; -+ -+ lockdep_assert_held(&mutex->lock); -+ -+ list_for_each_entry(entry, &mutex->any_waiters, node) { -+ struct ntsync_q *q = entry->q; -+ -+ if (mutex->u.mutex.count == UINT_MAX) -+ break; -+ if (mutex->u.mutex.owner && mutex->u.mutex.owner != q->owner) -+ continue; -+ -+ if (atomic_cmpxchg(&q->signaled, -1, entry->index) == -1) { -+ mutex->u.mutex.count++; -+ mutex->u.mutex.owner = q->owner; -+ wake_up_process(q->task); -+ } -+ } -+} -+ - /* - * Actually change the semaphore state, returning -EOVERFLOW if it is made - * invalid. -@@ -374,6 +409,33 @@ static int ntsync_create_sem(struct ntsync_device *dev, void __user *argp) - return put_user(fd, &user_args->sem); - } - -+static int ntsync_create_mutex(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_mutex_args __user *user_args = argp; -+ struct ntsync_mutex_args args; -+ struct ntsync_obj *mutex; -+ int fd; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ if (!args.owner != !args.count) -+ return -EINVAL; -+ -+ mutex = ntsync_alloc_obj(dev, NTSYNC_TYPE_MUTEX); -+ if (!mutex) -+ return -ENOMEM; -+ mutex->u.mutex.count = args.count; -+ mutex->u.mutex.owner = args.owner; -+ fd = ntsync_obj_get_fd(mutex); -+ if (fd < 0) { -+ kfree(mutex); -+ return fd; -+ } -+ -+ return put_user(fd, &user_args->mutex); -+} -+ - static struct ntsync_obj *get_obj(struct ntsync_device *dev, int fd) - { - struct file *file = fget(fd); -@@ -493,6 +555,9 @@ static void try_wake_any_obj(struct ntsync_obj *obj) - case NTSYNC_TYPE_SEM: - try_wake_any_sem(obj); - break; -+ case NTSYNC_TYPE_MUTEX: -+ try_wake_any_mutex(obj); -+ break; - } - } - -@@ -681,6 +746,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - void __user *argp = (void __user *)parm; - - switch (cmd) { -+ case NTSYNC_IOC_CREATE_MUTEX: -+ return ntsync_create_mutex(dev, argp); - case NTSYNC_IOC_CREATE_SEM: - return ntsync_create_sem(dev, argp); - case NTSYNC_IOC_WAIT_ALL: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 19c37e27a4f8..8ac9d419c360 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -16,6 +16,12 @@ struct ntsync_sem_args { - __u32 max; - }; - -+struct ntsync_mutex_args { -+ __u32 mutex; -+ __u32 owner; -+ __u32 count; -+}; -+ - struct ntsync_wait_args { - __u64 timeout; - __u64 objs; -@@ -30,6 +36,7 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_CREATE_SEM _IOWR('N', 0x80, struct ntsync_sem_args) - #define NTSYNC_IOC_WAIT_ANY _IOWR('N', 0x82, struct ntsync_wait_args) - #define NTSYNC_IOC_WAIT_ALL _IOWR('N', 0x83, struct ntsync_wait_args) -+#define NTSYNC_IOC_CREATE_MUTEX _IOWR('N', 0x84, struct ntsync_sem_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0006-[PATCH_v2_7_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_UNLOCK..patch b/linux-gcc/linux6.8-zen/patches/0006-[PATCH_v2_7_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_UNLOCK..patch deleted file mode 100644 index 97e5ace..0000000 --- a/linux-gcc/linux6.8-zen/patches/0006-[PATCH_v2_7_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_UNLOCK..patch +++ /dev/null @@ -1,107 +0,0 @@ -This corresponds to the NT syscall NtReleaseMutant(). - -This syscall decrements the mutex's recursion count by one, and returns the -previous value. If the mutex is not owned by the given owner ID, the function -instead fails and returns -EPERM. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 64 +++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 65 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 6f7086d0440a..222ebead8eba 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -312,6 +312,68 @@ static int ntsync_sem_post(struct ntsync_obj *sem, void __user *argp) - return ret; - } - -+/* -+ * Actually change the mutex state, returning -EPERM if not the owner. -+ */ -+static int unlock_mutex_state(struct ntsync_obj *mutex, -+ const struct ntsync_mutex_args *args) -+{ -+ lockdep_assert_held(&mutex->lock); -+ -+ if (mutex->u.mutex.owner != args->owner) -+ return -EPERM; -+ -+ if (!--mutex->u.mutex.count) -+ mutex->u.mutex.owner = 0; -+ return 0; -+} -+ -+static int ntsync_mutex_unlock(struct ntsync_obj *mutex, void __user *argp) -+{ -+ struct ntsync_mutex_args __user *user_args = argp; -+ struct ntsync_device *dev = mutex->dev; -+ struct ntsync_mutex_args args; -+ __u32 prev_count; -+ int ret; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ if (!args.owner) -+ return -EINVAL; -+ -+ if (mutex->type != NTSYNC_TYPE_MUTEX) -+ return -EINVAL; -+ -+ if (atomic_read(&mutex->all_hint) > 0) { -+ spin_lock(&dev->wait_all_lock); -+ spin_lock_nest_lock(&mutex->lock, &dev->wait_all_lock); -+ -+ prev_count = mutex->u.mutex.count; -+ ret = unlock_mutex_state(mutex, &args); -+ if (!ret) { -+ try_wake_all_obj(dev, mutex); -+ try_wake_any_mutex(mutex); -+ } -+ -+ spin_unlock(&mutex->lock); -+ spin_unlock(&dev->wait_all_lock); -+ } else { -+ spin_lock(&mutex->lock); -+ -+ prev_count = mutex->u.mutex.count; -+ ret = unlock_mutex_state(mutex, &args); -+ if (!ret) -+ try_wake_any_mutex(mutex); -+ -+ spin_unlock(&mutex->lock); -+ } -+ -+ if (!ret && put_user(prev_count, &user_args->count)) -+ ret = -EFAULT; -+ -+ return ret; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -331,6 +393,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - switch (cmd) { - case NTSYNC_IOC_SEM_POST: - return ntsync_sem_post(obj, argp); -+ case NTSYNC_IOC_MUTEX_UNLOCK: -+ return ntsync_mutex_unlock(obj, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 8ac9d419c360..265503d441b1 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -39,5 +39,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_CREATE_MUTEX _IOWR('N', 0x84, struct ntsync_sem_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) -+#define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) - - #endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0007-[PATCH_v2_8_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_KILL..patch b/linux-gcc/linux6.8-zen/patches/0007-[PATCH_v2_8_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_KILL..patch deleted file mode 100644 index ec55ac0..0000000 --- a/linux-gcc/linux6.8-zen/patches/0007-[PATCH_v2_8_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_KILL..patch +++ /dev/null @@ -1,166 +0,0 @@ -This does not correspond to any NT syscall. Rather, when a thread dies, it -should be called by the NT emulator for each mutex. - -NT mutexes are robust (in the pthread sense). When an NT thread dies, any -mutexes it owned are immediately released. Acquisition of those mutexes by other -threads will return a special value indicating that the mutex was abandoned, -like EOWNERDEAD returned from pthread_mutex_lock(), and EOWNERDEAD is indeed -used here for that purpose. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 71 +++++++++++++++++++++++++++++++++++-- - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 70 insertions(+), 2 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 222ebead8eba..a3466be50c45 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -57,6 +57,7 @@ struct ntsync_obj { - struct { - __u32 count; - __u32 owner; -+ bool ownerdead; - } mutex; - } u; - -@@ -109,6 +110,7 @@ struct ntsync_q { - atomic_t signaled; - - bool all; -+ bool ownerdead; - __u32 count; - struct ntsync_q_entry entries[]; - }; -@@ -184,6 +186,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; -@@ -243,6 +248,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); -@@ -374,6 +382,62 @@ static int ntsync_mutex_unlock(struct ntsync_obj *mutex, void __user *argp) - return ret; - } - -+/* -+ * Actually change the mutex state to mark its owner as dead, -+ * returning -EPERM if not the owner. -+ */ -+static int kill_mutex_state(struct ntsync_obj *mutex, __u32 owner) -+{ -+ lockdep_assert_held(&mutex->lock); -+ -+ if (mutex->u.mutex.owner != owner) -+ return -EPERM; -+ -+ mutex->u.mutex.ownerdead = true; -+ mutex->u.mutex.owner = 0; -+ mutex->u.mutex.count = 0; -+ return 0; -+} -+ -+static int ntsync_mutex_kill(struct ntsync_obj *mutex, void __user *argp) -+{ -+ struct ntsync_device *dev = mutex->dev; -+ __u32 owner; -+ int ret; -+ -+ if (get_user(owner, (__u32 __user *)argp)) -+ return -EFAULT; -+ if (!owner) -+ return -EINVAL; -+ -+ if (mutex->type != NTSYNC_TYPE_MUTEX) -+ return -EINVAL; -+ -+ if (atomic_read(&mutex->all_hint) > 0) { -+ spin_lock(&dev->wait_all_lock); -+ spin_lock_nest_lock(&mutex->lock, &dev->wait_all_lock); -+ -+ ret = kill_mutex_state(mutex, owner); -+ if (!ret) { -+ try_wake_all_obj(dev, mutex); -+ try_wake_any_mutex(mutex); -+ } -+ -+ spin_unlock(&mutex->lock); -+ spin_unlock(&dev->wait_all_lock); -+ } else { -+ spin_lock(&mutex->lock); -+ -+ ret = kill_mutex_state(mutex, owner); -+ if (!ret) -+ try_wake_any_mutex(mutex); -+ -+ spin_unlock(&mutex->lock); -+ } -+ -+ return ret; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -395,6 +459,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_sem_post(obj, argp); - case NTSYNC_IOC_MUTEX_UNLOCK: - return ntsync_mutex_unlock(obj, argp); -+ case NTSYNC_IOC_MUTEX_KILL: -+ return ntsync_mutex_kill(obj, argp); - default: - return -ENOIOCTLCMD; - } -@@ -579,6 +645,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++) { -@@ -686,7 +753,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; -@@ -767,7 +834,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; -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 265503d441b1..4800941fcbda 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -40,5 +40,6 @@ struct ntsync_wait_args { - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - #define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) -+#define NTSYNC_IOC_MUTEX_KILL _IOW ('N', 0x86, __u32) - - #endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0008-[PATCH_v2_9_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_EVENT..patch b/linux-gcc/linux6.8-zen/patches/0008-[PATCH_v2_9_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_EVENT..patch deleted file mode 100644 index 7376a14..0000000 --- a/linux-gcc/linux6.8-zen/patches/0008-[PATCH_v2_9_31]_ntsync:_Introduce_NTSYNC_IOC_CREATE_EVENT..patch +++ /dev/null @@ -1,165 +0,0 @@ -This correspond to the NT syscall NtCreateEvent(). - -An NT event holds a single bit of state denoting whether it is signaled or -unsignaled. - -There are two types of events: manual-reset and automatic-reset. When an -automatic-reset event is acquired via a wait function, its state is reset to -unsignaled. Manual-reset events are not affected by wait functions. - -Whether the event is manual-reset, and its initial state, are specified at -creation time. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 60 +++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 7 +++++ - 2 files changed, 67 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index a3466be50c45..17dd47d06e0a 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -25,6 +25,7 @@ - enum ntsync_type { - NTSYNC_TYPE_SEM, - NTSYNC_TYPE_MUTEX, -+ NTSYNC_TYPE_EVENT, - }; - - /* -@@ -59,6 +60,10 @@ struct ntsync_obj { - __u32 owner; - bool ownerdead; - } mutex; -+ struct { -+ bool manual; -+ bool signaled; -+ } event; - } u; - - /* -@@ -143,6 +148,8 @@ static bool is_signaled(struct ntsync_obj *obj, __u32 owner) - if (obj->u.mutex.owner && obj->u.mutex.owner != owner) - return false; - return obj->u.mutex.count < UINT_MAX; -+ case NTSYNC_TYPE_EVENT: -+ return obj->u.event.signaled; - } - - WARN(1, "bad object type %#x\n", obj->type); -@@ -192,6 +199,10 @@ static void try_wake_all(struct ntsync_device *dev, struct ntsync_q *q, - obj->u.mutex.count++; - obj->u.mutex.owner = q->owner; - break; -+ case NTSYNC_TYPE_EVENT: -+ if (!obj->u.event.manual) -+ obj->u.event.signaled = false; -+ break; - } - } - wake_up_process(q->task); -@@ -258,6 +269,26 @@ static void try_wake_any_mutex(struct ntsync_obj *mutex) - } - } - -+static void try_wake_any_event(struct ntsync_obj *event) -+{ -+ struct ntsync_q_entry *entry; -+ -+ lockdep_assert_held(&event->lock); -+ -+ list_for_each_entry(entry, &event->any_waiters, node) { -+ struct ntsync_q *q = entry->q; -+ -+ if (!event->u.event.signaled) -+ break; -+ -+ if (atomic_cmpxchg(&q->signaled, -1, entry->index) == -1) { -+ if (!event->u.event.manual) -+ event->u.event.signaled = false; -+ wake_up_process(q->task); -+ } -+ } -+} -+ - /* - * Actually change the semaphore state, returning -EOVERFLOW if it is made - * invalid. -@@ -566,6 +597,30 @@ static int ntsync_create_mutex(struct ntsync_device *dev, void __user *argp) - return put_user(fd, &user_args->mutex); - } - -+static int ntsync_create_event(struct ntsync_device *dev, void __user *argp) -+{ -+ struct ntsync_event_args __user *user_args = argp; -+ struct ntsync_event_args args; -+ struct ntsync_obj *event; -+ int fd; -+ -+ if (copy_from_user(&args, argp, sizeof(args))) -+ return -EFAULT; -+ -+ event = ntsync_alloc_obj(dev, NTSYNC_TYPE_EVENT); -+ if (!event) -+ return -ENOMEM; -+ event->u.event.manual = args.manual; -+ event->u.event.signaled = args.signaled; -+ fd = ntsync_obj_get_fd(event); -+ if (fd < 0) { -+ kfree(event); -+ return fd; -+ } -+ -+ return put_user(fd, &user_args->event); -+} -+ - static struct ntsync_obj *get_obj(struct ntsync_device *dev, int fd) - { - struct file *file = fget(fd); -@@ -689,6 +744,9 @@ static void try_wake_any_obj(struct ntsync_obj *obj) - case NTSYNC_TYPE_MUTEX: - try_wake_any_mutex(obj); - break; -+ case NTSYNC_TYPE_EVENT: -+ try_wake_any_event(obj); -+ break; - } - } - -@@ -877,6 +935,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd, - void __user *argp = (void __user *)parm; - - switch (cmd) { -+ case NTSYNC_IOC_CREATE_EVENT: -+ return ntsync_create_event(dev, argp); - case NTSYNC_IOC_CREATE_MUTEX: - return ntsync_create_mutex(dev, argp); - case NTSYNC_IOC_CREATE_SEM: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 4800941fcbda..040cbdb39033 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -22,6 +22,12 @@ struct ntsync_mutex_args { - __u32 count; - }; - -+struct ntsync_event_args { -+ __u32 event; -+ __u32 manual; -+ __u32 signaled; -+}; -+ - struct ntsync_wait_args { - __u64 timeout; - __u64 objs; -@@ -37,6 +43,7 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_WAIT_ANY _IOWR('N', 0x82, struct ntsync_wait_args) - #define NTSYNC_IOC_WAIT_ALL _IOWR('N', 0x83, struct ntsync_wait_args) - #define NTSYNC_IOC_CREATE_MUTEX _IOWR('N', 0x84, struct ntsync_sem_args) -+#define NTSYNC_IOC_CREATE_EVENT _IOWR('N', 0x87, struct ntsync_event_args) - - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - #define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0009-[PATCH_v2_10_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_SET..patch b/linux-gcc/linux6.8-zen/patches/0009-[PATCH_v2_10_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_SET..patch deleted file mode 100644 index 58e9472..0000000 --- a/linux-gcc/linux6.8-zen/patches/0009-[PATCH_v2_10_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_SET..patch +++ /dev/null @@ -1,78 +0,0 @@ -This corresponds to the NT syscall NtSetEvent(). - -This sets the event to the signaled state, and returns its previous state. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 37 +++++++++++++++++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 38 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 17dd47d06e0a..edfbf11cafe0 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -469,6 +469,41 @@ static int ntsync_mutex_kill(struct ntsync_obj *mutex, void __user *argp) - return ret; - } - -+static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) -+{ -+ struct ntsync_device *dev = event->dev; -+ __u32 prev_state; -+ -+ if (event->type != NTSYNC_TYPE_EVENT) -+ return -EINVAL; -+ -+ if (atomic_read(&event->all_hint) > 0) { -+ spin_lock(&dev->wait_all_lock); -+ spin_lock_nest_lock(&event->lock, &dev->wait_all_lock); -+ -+ prev_state = event->u.event.signaled; -+ event->u.event.signaled = true; -+ try_wake_all_obj(dev, event); -+ try_wake_any_event(event); -+ -+ spin_unlock(&event->lock); -+ spin_unlock(&dev->wait_all_lock); -+ } else { -+ spin_lock(&event->lock); -+ -+ prev_state = event->u.event.signaled; -+ event->u.event.signaled = true; -+ try_wake_any_event(event); -+ -+ spin_unlock(&event->lock); -+ } -+ -+ if (put_user(prev_state, (__u32 __user *)argp)) -+ return -EFAULT; -+ -+ return 0; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -492,6 +527,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_mutex_unlock(obj, argp); - case NTSYNC_IOC_MUTEX_KILL: - return ntsync_mutex_kill(obj, argp); -+ case NTSYNC_IOC_EVENT_SET: -+ return ntsync_event_set(obj, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 040cbdb39033..af518530bffd 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -48,5 +48,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_SEM_POST _IOWR('N', 0x81, __u32) - #define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) - #define NTSYNC_IOC_MUTEX_KILL _IOW ('N', 0x86, __u32) -+#define NTSYNC_IOC_EVENT_SET _IOR ('N', 0x88, __u32) - - #endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0010-[PATCH_v2_11_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_RESET..patch b/linux-gcc/linux6.8-zen/patches/0010-[PATCH_v2_11_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_RESET..patch deleted file mode 100644 index 88cdda0..0000000 --- a/linux-gcc/linux6.8-zen/patches/0010-[PATCH_v2_11_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_RESET..patch +++ /dev/null @@ -1,63 +0,0 @@ -This corresponds to the NT syscall NtResetEvent(). - -This sets the event to the unsignaled state, and returns its previous state. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 22 ++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 23 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index edfbf11cafe0..fa4c3fa1e496 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -504,6 +504,26 @@ static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) - return 0; - } - -+static int ntsync_event_reset(struct ntsync_obj *event, void __user *argp) -+{ -+ __u32 prev_state; -+ -+ if (event->type != NTSYNC_TYPE_EVENT) -+ return -EINVAL; -+ -+ spin_lock(&event->lock); -+ -+ prev_state = event->u.event.signaled; -+ event->u.event.signaled = false; -+ -+ spin_unlock(&event->lock); -+ -+ if (put_user(prev_state, (__u32 __user *)argp)) -+ return -EFAULT; -+ -+ return 0; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -529,6 +549,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_mutex_kill(obj, argp); - case NTSYNC_IOC_EVENT_SET: - return ntsync_event_set(obj, argp); -+ case NTSYNC_IOC_EVENT_RESET: -+ return ntsync_event_reset(obj, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index af518530bffd..6963356ee3f7 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -49,5 +49,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('N', 0x85, struct ntsync_mutex_args) - #define NTSYNC_IOC_MUTEX_KILL _IOW ('N', 0x86, __u32) - #define NTSYNC_IOC_EVENT_SET _IOR ('N', 0x88, __u32) -+#define NTSYNC_IOC_EVENT_RESET _IOR ('N', 0x89, __u32) - - #endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0011-[PATCH_v2_12_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_PULSE..patch b/linux-gcc/linux6.8-zen/patches/0011-[PATCH_v2_12_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_PULSE..patch deleted file mode 100644 index 76aa1a7..0000000 --- a/linux-gcc/linux6.8-zen/patches/0011-[PATCH_v2_12_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_PULSE..patch +++ /dev/null @@ -1,70 +0,0 @@ -This corresponds to the NT syscall NtPulseEvent(). - -This wakes up any waiters as if the event had been set, but does not set the -event, instead resetting it if it had been signalled. Thus, for a manual-reset -event, all waiters are woken, whereas for an auto-reset event, at most one -waiter is woken. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 10 ++++++++-- - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 9 insertions(+), 2 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index fa4c3fa1e496..b9b4127a6c9f 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -469,7 +469,7 @@ static int ntsync_mutex_kill(struct ntsync_obj *mutex, void __user *argp) - return ret; - } - --static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) -+static int ntsync_event_set(struct ntsync_obj *event, void __user *argp, bool pulse) - { - struct ntsync_device *dev = event->dev; - __u32 prev_state; -@@ -485,6 +485,8 @@ static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) - event->u.event.signaled = true; - try_wake_all_obj(dev, event); - try_wake_any_event(event); -+ if (pulse) -+ event->u.event.signaled = false; - - spin_unlock(&event->lock); - spin_unlock(&dev->wait_all_lock); -@@ -494,6 +496,8 @@ static int ntsync_event_set(struct ntsync_obj *event, void __user *argp) - prev_state = event->u.event.signaled; - event->u.event.signaled = true; - try_wake_any_event(event); -+ if (pulse) -+ event->u.event.signaled = false; - - spin_unlock(&event->lock); - } -@@ -548,9 +552,11 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - case NTSYNC_IOC_MUTEX_KILL: - return ntsync_mutex_kill(obj, argp); - case NTSYNC_IOC_EVENT_SET: -- return ntsync_event_set(obj, argp); -+ return ntsync_event_set(obj, argp, false); - case NTSYNC_IOC_EVENT_RESET: - return ntsync_event_reset(obj, argp); -+ case NTSYNC_IOC_EVENT_PULSE: -+ return ntsync_event_set(obj, argp, true); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 6963356ee3f7..72047f36c45d 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -50,5 +50,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_MUTEX_KILL _IOW ('N', 0x86, __u32) - #define NTSYNC_IOC_EVENT_SET _IOR ('N', 0x88, __u32) - #define NTSYNC_IOC_EVENT_RESET _IOR ('N', 0x89, __u32) -+#define NTSYNC_IOC_EVENT_PULSE _IOR ('N', 0x8a, __u32) - - #endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0012-[PATCH_v2_13_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_READ..patch b/linux-gcc/linux6.8-zen/patches/0012-[PATCH_v2_13_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_READ..patch deleted file mode 100644 index e32f7ef..0000000 --- a/linux-gcc/linux6.8-zen/patches/0012-[PATCH_v2_13_31]_ntsync:_Introduce_NTSYNC_IOC_SEM_READ..patch +++ /dev/null @@ -1,62 +0,0 @@ -This corresponds to the NT syscall NtQuerySemaphore(). - -This returns the current count and maximum count of the semaphore. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 21 +++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 22 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index b9b4127a6c9f..0daaeeeba051 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -528,6 +528,25 @@ static int ntsync_event_reset(struct ntsync_obj *event, void __user *argp) - return 0; - } - -+static int ntsync_sem_read(struct ntsync_obj *sem, void __user *argp) -+{ -+ struct ntsync_sem_args __user *user_args = argp; -+ struct ntsync_sem_args args; -+ -+ if (sem->type != NTSYNC_TYPE_SEM) -+ return -EINVAL; -+ -+ args.sem = 0; -+ spin_lock(&sem->lock); -+ args.count = sem->u.sem.count; -+ args.max = sem->u.sem.max; -+ spin_unlock(&sem->lock); -+ -+ if (copy_to_user(user_args, &args, sizeof(args))) -+ return -EFAULT; -+ return 0; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -547,6 +566,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - switch (cmd) { - case NTSYNC_IOC_SEM_POST: - return ntsync_sem_post(obj, argp); -+ case NTSYNC_IOC_SEM_READ: -+ return ntsync_sem_read(obj, argp); - case NTSYNC_IOC_MUTEX_UNLOCK: - return ntsync_mutex_unlock(obj, argp); - case NTSYNC_IOC_MUTEX_KILL: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 72047f36c45d..42f51dc4e57e 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -51,5 +51,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_EVENT_SET _IOR ('N', 0x88, __u32) - #define NTSYNC_IOC_EVENT_RESET _IOR ('N', 0x89, __u32) - #define NTSYNC_IOC_EVENT_PULSE _IOR ('N', 0x8a, __u32) -+#define NTSYNC_IOC_SEM_READ _IOR ('N', 0x8b, struct ntsync_sem_args) - - #endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0013-[PATCH_v2_14_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_READ..patch b/linux-gcc/linux6.8-zen/patches/0013-[PATCH_v2_14_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_READ..patch deleted file mode 100644 index b97bd13..0000000 --- a/linux-gcc/linux6.8-zen/patches/0013-[PATCH_v2_14_31]_ntsync:_Introduce_NTSYNC_IOC_MUTEX_READ..patch +++ /dev/null @@ -1,64 +0,0 @@ -This corresponds to the NT syscall NtQueryMutant(). - -This returns the recursion count, owner, and abandoned state of the mutex. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 23 +++++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 24 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 0daaeeeba051..b07510035c1f 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -547,6 +547,27 @@ static int ntsync_sem_read(struct ntsync_obj *sem, void __user *argp) - return 0; - } - -+static int ntsync_mutex_read(struct ntsync_obj *mutex, void __user *argp) -+{ -+ struct ntsync_mutex_args __user *user_args = argp; -+ struct ntsync_mutex_args args; -+ int ret; -+ -+ if (mutex->type != NTSYNC_TYPE_MUTEX) -+ return -EINVAL; -+ -+ args.mutex = 0; -+ spin_lock(&mutex->lock); -+ args.count = mutex->u.mutex.count; -+ args.owner = mutex->u.mutex.owner; -+ ret = mutex->u.mutex.ownerdead ? -EOWNERDEAD : 0; -+ spin_unlock(&mutex->lock); -+ -+ if (copy_to_user(user_args, &args, sizeof(args))) -+ return -EFAULT; -+ return ret; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -572,6 +593,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_mutex_unlock(obj, argp); - case NTSYNC_IOC_MUTEX_KILL: - return ntsync_mutex_kill(obj, argp); -+ case NTSYNC_IOC_MUTEX_READ: -+ return ntsync_mutex_read(obj, argp); - case NTSYNC_IOC_EVENT_SET: - return ntsync_event_set(obj, argp, false); - case NTSYNC_IOC_EVENT_RESET: -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 42f51dc4e57e..25f3296cfabf 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -52,5 +52,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_EVENT_RESET _IOR ('N', 0x89, __u32) - #define NTSYNC_IOC_EVENT_PULSE _IOR ('N', 0x8a, __u32) - #define NTSYNC_IOC_SEM_READ _IOR ('N', 0x8b, struct ntsync_sem_args) -+#define NTSYNC_IOC_MUTEX_READ _IOR ('N', 0x8c, struct ntsync_mutex_args) - - #endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0014-[PATCH_v2_15_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_READ..patch b/linux-gcc/linux6.8-zen/patches/0014-[PATCH_v2_15_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_READ..patch deleted file mode 100644 index 476ae09..0000000 --- a/linux-gcc/linux6.8-zen/patches/0014-[PATCH_v2_15_31]_ntsync:_Introduce_NTSYNC_IOC_EVENT_READ..patch +++ /dev/null @@ -1,62 +0,0 @@ -This corresponds to the NT syscall NtQueryEvent(). - -This returns the signaled state of the event and whether it is manual-reset. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 21 +++++++++++++++++++++ - include/uapi/linux/ntsync.h | 1 + - 2 files changed, 22 insertions(+) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index b07510035c1f..981a1545192c 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -568,6 +568,25 @@ static int ntsync_mutex_read(struct ntsync_obj *mutex, void __user *argp) - return ret; - } - -+static int ntsync_event_read(struct ntsync_obj *event, void __user *argp) -+{ -+ struct ntsync_event_args __user *user_args = argp; -+ struct ntsync_event_args args; -+ -+ if (event->type != NTSYNC_TYPE_EVENT) -+ return -EINVAL; -+ -+ args.event = 0; -+ spin_lock(&event->lock); -+ args.manual = event->u.event.manual; -+ args.signaled = event->u.event.signaled; -+ spin_unlock(&event->lock); -+ -+ if (copy_to_user(user_args, &args, sizeof(args))) -+ return -EFAULT; -+ return 0; -+} -+ - static int ntsync_obj_release(struct inode *inode, struct file *file) - { - struct ntsync_obj *obj = file->private_data; -@@ -601,6 +620,8 @@ static long ntsync_obj_ioctl(struct file *file, unsigned int cmd, - return ntsync_event_reset(obj, argp); - case NTSYNC_IOC_EVENT_PULSE: - return ntsync_event_set(obj, argp, true); -+ case NTSYNC_IOC_EVENT_READ: -+ return ntsync_event_read(obj, argp); - default: - return -ENOIOCTLCMD; - } -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 25f3296cfabf..03c95e5a398f 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -53,5 +53,6 @@ struct ntsync_wait_args { - #define NTSYNC_IOC_EVENT_PULSE _IOR ('N', 0x8a, __u32) - #define NTSYNC_IOC_SEM_READ _IOR ('N', 0x8b, struct ntsync_sem_args) - #define NTSYNC_IOC_MUTEX_READ _IOR ('N', 0x8c, struct ntsync_mutex_args) -+#define NTSYNC_IOC_EVENT_READ _IOR ('N', 0x8d, struct ntsync_event_args) - - #endif --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0015-[PATCH_v2_16_31]_ntsync:_Introduce_alertable_waits..patch b/linux-gcc/linux6.8-zen/patches/0015-[PATCH_v2_16_31]_ntsync:_Introduce_alertable_waits..patch deleted file mode 100644 index ce53af5..0000000 --- a/linux-gcc/linux6.8-zen/patches/0015-[PATCH_v2_16_31]_ntsync:_Introduce_alertable_waits..patch +++ /dev/null @@ -1,184 +0,0 @@ -NT waits can optionally be made "alertable". This is a special channel for -thread wakeup that is mildly similar to SIGIO. A thread has an internal single -bit of "alerted" state, and if a thread is made alerted while an alertable wait, -the wait will return a special value, consume the "alerted" state, and will not -consume any of its objects. - -Alerts are implemented using events; the user-space NT emulator is expected to -create an internal ntsync event for each thread and pass that event to wait -functions. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 68 ++++++++++++++++++++++++++++++++----- - include/uapi/linux/ntsync.h | 2 +- - 2 files changed, 60 insertions(+), 10 deletions(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 981a1545192c..0055b4671808 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -808,22 +808,29 @@ static int setup_wait(struct ntsync_device *dev, - const struct ntsync_wait_args *args, bool all, - struct ntsync_q **ret_q) - { -+ int fds[NTSYNC_MAX_WAIT_COUNT + 1]; - const __u32 count = args->count; -- int fds[NTSYNC_MAX_WAIT_COUNT]; - struct ntsync_q *q; -+ __u32 total_count; - __u32 i, j; - -- if (!args->owner || args->pad) -+ if (!args->owner) - return -EINVAL; - - if (args->count > NTSYNC_MAX_WAIT_COUNT) - return -EINVAL; - -+ total_count = count; -+ if (args->alert) -+ total_count++; -+ - if (copy_from_user(fds, u64_to_user_ptr(args->objs), - array_size(count, sizeof(*fds)))) - return -EFAULT; -+ if (args->alert) -+ fds[count] = args->alert; - -- q = kmalloc(struct_size(q, entries, count), GFP_KERNEL); -+ q = kmalloc(struct_size(q, entries, total_count), GFP_KERNEL); - if (!q) - return -ENOMEM; - q->task = current; -@@ -833,7 +840,7 @@ static int setup_wait(struct ntsync_device *dev, - q->ownerdead = false; - q->count = count; - -- for (i = 0; i < count; i++) { -+ for (i = 0; i < total_count; i++) { - struct ntsync_q_entry *entry = &q->entries[i]; - struct ntsync_obj *obj = get_obj(dev, fds[i]); - -@@ -883,9 +890,9 @@ static void try_wake_any_obj(struct ntsync_obj *obj) - static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - { - struct ntsync_wait_args args; -+ __u32 i, total_count; - struct ntsync_q *q; - int signaled; -- __u32 i; - int ret; - - if (copy_from_user(&args, argp, sizeof(args))) -@@ -895,9 +902,13 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - if (ret < 0) - return ret; - -+ total_count = args.count; -+ if (args.alert) -+ total_count++; -+ - /* queue ourselves */ - -- for (i = 0; i < args.count; i++) { -+ for (i = 0; i < total_count; i++) { - struct ntsync_q_entry *entry = &q->entries[i]; - struct ntsync_obj *obj = entry->obj; - -@@ -906,9 +917,15 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - spin_unlock(&obj->lock); - } - -- /* check if we are already signaled */ -+ /* -+ * Check if we are already signaled. -+ * -+ * Note that the API requires that normal objects are checked before -+ * the alert event. Hence we queue the alert event last, and check -+ * objects in order. -+ */ - -- for (i = 0; i < args.count; i++) { -+ for (i = 0; i < total_count; i++) { - struct ntsync_obj *obj = q->entries[i].obj; - - if (atomic_read(&q->signaled) != -1) -@@ -925,7 +942,7 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp) - - /* and finally, unqueue */ - -- for (i = 0; i < args.count; i++) { -+ for (i = 0; i < total_count; i++) { - struct ntsync_q_entry *entry = &q->entries[i]; - struct ntsync_obj *obj = entry->obj; - -@@ -985,6 +1002,14 @@ static int ntsync_wait_all(struct ntsync_device *dev, void __user *argp) - */ - list_add_tail(&entry->node, &obj->all_waiters); - } -+ if (args.alert) { -+ struct ntsync_q_entry *entry = &q->entries[args.count]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ spin_lock_nest_lock(&obj->lock, &dev->wait_all_lock); -+ list_add_tail(&entry->node, &obj->any_waiters); -+ spin_unlock(&obj->lock); -+ } - - /* check if we are already signaled */ - -@@ -992,6 +1017,21 @@ static int ntsync_wait_all(struct ntsync_device *dev, void __user *argp) - - spin_unlock(&dev->wait_all_lock); - -+ /* -+ * Check if the alert event is signaled, making sure to do so only -+ * after checking if the other objects are signaled. -+ */ -+ -+ if (args.alert) { -+ struct ntsync_obj *obj = q->entries[args.count].obj; -+ -+ if (atomic_read(&q->signaled) == -1) { -+ spin_lock(&obj->lock); -+ try_wake_any_obj(obj); -+ spin_unlock(&obj->lock); -+ } -+ } -+ - /* sleep */ - - ret = ntsync_schedule(q, &args); -@@ -1014,6 +1054,16 @@ static int ntsync_wait_all(struct ntsync_device *dev, void __user *argp) - - put_obj(obj); - } -+ if (args.alert) { -+ struct ntsync_q_entry *entry = &q->entries[args.count]; -+ struct ntsync_obj *obj = entry->obj; -+ -+ spin_lock_nest_lock(&obj->lock, &dev->wait_all_lock); -+ list_del(&entry->node); -+ spin_unlock(&obj->lock); -+ -+ put_obj(obj); -+ } - - spin_unlock(&dev->wait_all_lock); - -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 03c95e5a398f..555ae81b479a 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -34,7 +34,7 @@ struct ntsync_wait_args { - __u32 count; - __u32 owner; - __u32 index; -- __u32 pad; -+ __u32 alert; - }; - - #define NTSYNC_MAX_WAIT_COUNT 64 --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0016-[PATCH_v2_17_31]_ntsync:_Allow_waits_to_use_the_REALTIME_clock..patch b/linux-gcc/linux6.8-zen/patches/0016-[PATCH_v2_17_31]_ntsync:_Allow_waits_to_use_the_REALTIME_clock..patch deleted file mode 100644 index 6e15e88..0000000 --- a/linux-gcc/linux6.8-zen/patches/0016-[PATCH_v2_17_31]_ntsync:_Allow_waits_to_use_the_REALTIME_clock..patch +++ /dev/null @@ -1,79 +0,0 @@ -NtWaitForMultipleObjects() can receive a timeout in two forms, relative or -absolute. Relative timeouts are unaffected by changes to the system time and do -not count down while the system suspends; for absolute timeouts the opposite is -true. - -In order to make the interface and implementation simpler, the ntsync driver -only deals in absolute timeouts. However, we need to be able to emulate both -behaviours apropos suspension and time adjustment, which is achieved by allowing -either the MONOTONIC or REALTIME clock to be used. - -Signed-off-by: Elizabeth Figura ---- - drivers/misc/ntsync.c | 9 ++++++++- - include/uapi/linux/ntsync.h | 4 ++++ - 2 files changed, 12 insertions(+), 1 deletion(-) - -diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c -index 0055b4671808..f54c81dada3d 100644 ---- a/drivers/misc/ntsync.c -+++ b/drivers/misc/ntsync.c -@@ -778,11 +778,15 @@ static void put_obj(struct ntsync_obj *obj) - static int ntsync_schedule(const struct ntsync_q *q, const struct ntsync_wait_args *args) - { - ktime_t timeout = ns_to_ktime(args->timeout); -+ clockid_t clock = CLOCK_MONOTONIC; - ktime_t *timeout_ptr; - int ret = 0; - - timeout_ptr = (args->timeout == U64_MAX ? NULL : &timeout); - -+ if (args->flags & NTSYNC_WAIT_REALTIME) -+ clock = CLOCK_REALTIME; -+ - do { - if (signal_pending(current)) { - ret = -ERESTARTSYS; -@@ -794,7 +798,7 @@ static int ntsync_schedule(const struct ntsync_q *q, const struct ntsync_wait_ar - ret = 0; - break; - } -- ret = schedule_hrtimeout(timeout_ptr, HRTIMER_MODE_ABS); -+ ret = schedule_hrtimeout_range_clock(timeout_ptr, 0, HRTIMER_MODE_ABS, clock); - } while (ret < 0); - __set_current_state(TASK_RUNNING); - -@@ -817,6 +821,9 @@ static int setup_wait(struct ntsync_device *dev, - if (!args->owner) - return -EINVAL; - -+ if (args->pad || (args->flags & ~NTSYNC_WAIT_REALTIME)) -+ return -EINVAL; -+ - if (args->count > NTSYNC_MAX_WAIT_COUNT) - return -EINVAL; - -diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h -index 555ae81b479a..b5e835d8dba8 100644 ---- a/include/uapi/linux/ntsync.h -+++ b/include/uapi/linux/ntsync.h -@@ -28,6 +28,8 @@ struct ntsync_event_args { - __u32 signaled; - }; - -+#define NTSYNC_WAIT_REALTIME 0x1 -+ - struct ntsync_wait_args { - __u64 timeout; - __u64 objs; -@@ -35,6 +37,8 @@ struct ntsync_wait_args { - __u32 owner; - __u32 index; - __u32 alert; -+ __u32 flags; -+ __u32 pad; - }; - - #define NTSYNC_MAX_WAIT_COUNT 64 --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0017-[PATCH_v2_18_31]_selftests:_ntsync:_Add_some_tests_for_semaphore\n_state..patch" "b/linux-gcc/linux6.8-zen/patches/0017-[PATCH_v2_18_31]_selftests:_ntsync:_Add_some_tests_for_semaphore\n_state..patch" deleted file mode 100644 index 5d8c716..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0017-[PATCH_v2_18_31]_selftests:_ntsync:_Add_some_tests_for_semaphore\n_state..patch" +++ /dev/null @@ -1,208 +0,0 @@ -Wine has tests for its synchronization primitives, but these are more accessible -to kernel developers, and also allow us to test some edge cases that Wine does -not care about. - -This patch adds tests for semaphore-specific ioctls NTSYNC_IOC_SEM_POST and -NTSYNC_IOC_SEM_READ, and waiting on semaphores. - -Signed-off-by: Elizabeth Figura ---- - tools/testing/selftests/Makefile | 1 + - .../testing/selftests/drivers/ntsync/Makefile | 8 + - tools/testing/selftests/drivers/ntsync/config | 1 + - .../testing/selftests/drivers/ntsync/ntsync.c | 149 ++++++++++++++++++ - 4 files changed, 159 insertions(+) - 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 - -diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile -index 15b6a111c3be..6c714a4e6478 100644 ---- a/tools/testing/selftests/Makefile -+++ b/tools/testing/selftests/Makefile -@@ -15,6 +15,7 @@ TARGETS += cpu-hotplug - TARGETS += damon - TARGETS += dmabuf-heaps - TARGETS += drivers/dma-buf -+TARGETS += drivers/ntsync - TARGETS += drivers/s390x/uvdevice - TARGETS += drivers/net/bonding - TARGETS += drivers/net/team -diff --git a/tools/testing/selftests/drivers/ntsync/Makefile b/tools/testing/selftests/drivers/ntsync/Makefile -new file mode 100644 -index 000000000000..a34da5ccacf0 ---- /dev/null -+++ b/tools/testing/selftests/drivers/ntsync/Makefile -@@ -0,0 +1,8 @@ -+# SPDX-LICENSE-IDENTIFIER: GPL-2.0-only -+TEST_GEN_PROGS := ntsync -+ -+top_srcdir =../../../../.. -+CFLAGS += -I$(top_srcdir)/usr/include -+LDLIBS += -lpthread -+ -+include ../../lib.mk -diff --git a/tools/testing/selftests/drivers/ntsync/config b/tools/testing/selftests/drivers/ntsync/config -new file mode 100644 -index 000000000000..60539c826d06 ---- /dev/null -+++ b/tools/testing/selftests/drivers/ntsync/config -@@ -0,0 +1 @@ -+CONFIG_WINESYNC=y -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -new file mode 100644 -index 000000000000..1e145c6dfded ---- /dev/null -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -0,0 +1,149 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Various unit tests for the "ntsync" synchronization primitive driver. -+ * -+ * Copyright (C) 2021-2022 Elizabeth Figura -+ */ -+ -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+#include -+#include -+#include "../../kselftest_harness.h" -+ -+static int read_sem_state(int sem, __u32 *count, __u32 *max) -+{ -+ struct ntsync_sem_args args; -+ int ret; -+ -+ memset(&args, 0xcc, sizeof(args)); -+ ret = ioctl(sem, NTSYNC_IOC_SEM_READ, &args); -+ *count = args.count; -+ *max = args.max; -+ return ret; -+} -+ -+#define check_sem_state(sem, count, max) \ -+ ({ \ -+ __u32 __count, __max; \ -+ int ret = read_sem_state((sem), &__count, &__max); \ -+ EXPECT_EQ(0, ret); \ -+ EXPECT_EQ((count), __count); \ -+ EXPECT_EQ((max), __max); \ -+ }) -+ -+static int post_sem(int sem, __u32 *count) -+{ -+ return ioctl(sem, NTSYNC_IOC_SEM_POST, count); -+} -+ -+static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) -+{ -+ struct ntsync_wait_args args = {0}; -+ struct timespec timeout; -+ int ret; -+ -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ -+ args.timeout = timeout.tv_sec * 1000000000 + timeout.tv_nsec; -+ args.count = count; -+ args.objs = (uintptr_t)objs; -+ args.owner = owner; -+ args.index = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_WAIT_ANY, &args); -+ *index = args.index; -+ return ret; -+} -+ -+TEST(semaphore_state) -+{ -+ struct ntsync_sem_args sem_args; -+ struct timespec timeout; -+ __u32 count, index; -+ int fd, ret, sem; -+ -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 3; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ sem_args.count = 2; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ sem = sem_args.sem; -+ check_sem_state(sem, 2, 2); -+ -+ count = 0; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, count); -+ check_sem_state(sem, 2, 2); -+ -+ count = 1; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOVERFLOW, errno); -+ check_sem_state(sem, 2, 2); -+ -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem, 1, 2); -+ -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem, 0, 2); -+ -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ count = 3; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOVERFLOW, errno); -+ check_sem_state(sem, 0, 2); -+ -+ count = 2; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ check_sem_state(sem, 2, 2); -+ -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ ret = wait_any(fd, 1, &sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ -+ count = 1; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ check_sem_state(sem, 1, 2); -+ -+ count = ~0u; -+ ret = post_sem(sem, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOVERFLOW, errno); -+ check_sem_state(sem, 1, 2); -+ -+ close(sem); -+ -+ close(fd); -+} -+ -+TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0018-[PATCH_v2_19_31]_selftests:_ntsync:_Add_some_tests_for_mutex\n_state..patch" "b/linux-gcc/linux6.8-zen/patches/0018-[PATCH_v2_19_31]_selftests:_ntsync:_Add_some_tests_for_mutex\n_state..patch" deleted file mode 100644 index 316e7d1..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0018-[PATCH_v2_19_31]_selftests:_ntsync:_Add_some_tests_for_mutex\n_state..patch" +++ /dev/null @@ -1,222 +0,0 @@ -Test mutex-specific ioctls NTSYNC_IOC_MUTEX_UNLOCK and NTSYNC_IOC_MUTEX_READ, -and waiting on mutexes. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 196 ++++++++++++++++++ - 1 file changed, 196 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 1e145c6dfded..7cd0f40594fd 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -40,6 +40,39 @@ static int post_sem(int sem, __u32 *count) - return ioctl(sem, NTSYNC_IOC_SEM_POST, count); - } - -+static int read_mutex_state(int mutex, __u32 *count, __u32 *owner) -+{ -+ struct ntsync_mutex_args args; -+ int ret; -+ -+ memset(&args, 0xcc, sizeof(args)); -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &args); -+ *count = args.count; -+ *owner = args.owner; -+ return ret; -+} -+ -+#define check_mutex_state(mutex, count, owner) \ -+ ({ \ -+ __u32 __count, __owner; \ -+ int ret = read_mutex_state((mutex), &__count, &__owner); \ -+ EXPECT_EQ(0, ret); \ -+ EXPECT_EQ((count), __count); \ -+ EXPECT_EQ((owner), __owner); \ -+ }) -+ -+static int unlock_mutex(int mutex, __u32 owner, __u32 *count) -+{ -+ struct ntsync_mutex_args args; -+ int ret; -+ -+ args.owner = owner; -+ args.count = 0xdeadbeef; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_UNLOCK, &args); -+ *count = args.count; -+ return ret; -+} -+ - static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) - { - struct ntsync_wait_args args = {0}; -@@ -146,4 +179,167 @@ TEST(semaphore_state) - close(fd); - } - -+TEST(mutex_state) -+{ -+ struct ntsync_mutex_args mutex_args; -+ __u32 owner, count, index; -+ struct timespec timeout; -+ int fd, ret, mutex; -+ -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = 0; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 2; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = 2; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ mutex = mutex_args.mutex; -+ check_mutex_state(mutex, 2, 123); -+ -+ ret = unlock_mutex(mutex, 0, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ ret = unlock_mutex(mutex, 456, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EPERM, errno); -+ check_mutex_state(mutex, 2, 123); -+ -+ ret = unlock_mutex(mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, count); -+ check_mutex_state(mutex, 1, 123); -+ -+ ret = unlock_mutex(mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, count); -+ check_mutex_state(mutex, 0, 0); -+ -+ ret = unlock_mutex(mutex, 123, &count); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EPERM, errno); -+ -+ ret = wait_any(fd, 1, &mutex, 456, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 1, 456); -+ -+ ret = wait_any(fd, 1, &mutex, 456, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 2, 456); -+ -+ ret = unlock_mutex(mutex, 456, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, count); -+ check_mutex_state(mutex, 1, 456); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ owner = 0; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ owner = 123; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EPERM, errno); -+ check_mutex_state(mutex, 1, 456); -+ -+ owner = 456; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(0, ret); -+ -+ memset(&mutex_args, 0xcc, sizeof(mutex_args)); -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, mutex_args.count); -+ EXPECT_EQ(0, mutex_args.owner); -+ -+ memset(&mutex_args, 0xcc, sizeof(mutex_args)); -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, mutex_args.count); -+ EXPECT_EQ(0, mutex_args.owner); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 1, 123); -+ -+ owner = 123; -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(0, ret); -+ -+ memset(&mutex_args, 0xcc, sizeof(mutex_args)); -+ ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, mutex_args.count); -+ EXPECT_EQ(0, mutex_args.owner); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 1, 123); -+ -+ close(mutex); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 0; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ mutex = mutex_args.mutex; -+ check_mutex_state(mutex, 0, 0); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_mutex_state(mutex, 1, 123); -+ -+ close(mutex); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = ~0u; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ mutex = mutex_args.mutex; -+ check_mutex_state(mutex, ~0u, 123); -+ -+ ret = wait_any(fd, 1, &mutex, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ close(mutex); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0019-[PATCH_v2_20_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ANY..patch" "b/linux-gcc/linux6.8-zen/patches/0019-[PATCH_v2_20_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ANY..patch" deleted file mode 100644 index 6484738..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0019-[PATCH_v2_20_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ANY..patch" +++ /dev/null @@ -1,139 +0,0 @@ -Test basic synchronous functionality of NTSYNC_IOC_WAIT_ANY, when objects are -considered signaled or not signaled, and how they are affected by a successful -wait. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 119 ++++++++++++++++++ - 1 file changed, 119 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 7cd0f40594fd..40ad8cbd3138 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -342,4 +342,123 @@ TEST(mutex_state) - close(fd); - } - -+TEST(test_wait_any) -+{ -+ int objs[NTSYNC_MAX_WAIT_COUNT + 1], fd, ret; -+ struct ntsync_mutex_args mutex_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ __u32 owner, index, count, i; -+ struct timespec timeout; -+ -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 2; -+ sem_args.max = 3; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 0; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ -+ objs[0] = sem_args.sem; -+ objs[1] = mutex_args.mutex; -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 0, 0); -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 0, 0); -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ count = 1; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ ret = wait_any(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 2, 123); -+ -+ ret = wait_any(fd, 2, objs, 456, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ owner = 123; -+ ret = ioctl(mutex_args.mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any(fd, 2, objs, 456, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ EXPECT_EQ(1, index); -+ -+ ret = wait_any(fd, 2, objs, 456, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, index); -+ -+ /* test waiting on the same object twice */ -+ count = 2; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ -+ objs[0] = objs[1] = sem_args.sem; -+ ret = wait_any(fd, 2, objs, 456, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 1, 3); -+ -+ ret = wait_any(fd, 0, NULL, 456, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ for (i = 0; i < NTSYNC_MAX_WAIT_COUNT + 1; ++i) -+ objs[i] = sem_args.sem; -+ -+ ret = wait_any(fd, NTSYNC_MAX_WAIT_COUNT, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = wait_any(fd, NTSYNC_MAX_WAIT_COUNT + 1, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ ret = wait_any(fd, -1, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ close(sem_args.sem); -+ close(mutex_args.mutex); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0020-[PATCH_v2_21_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ALL..patch" "b/linux-gcc/linux6.8-zen/patches/0020-[PATCH_v2_21_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ALL..patch" deleted file mode 100644 index ebe93e0..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0020-[PATCH_v2_21_31]_selftests:_ntsync:_Add_some_tests_for\n_NTSYNC_IOC_WAIT_ALL..patch" +++ /dev/null @@ -1,136 +0,0 @@ -Test basic synchronous functionality of NTSYNC_IOC_WAIT_ALL, and when objects -are considered simultaneously signaled. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 99 ++++++++++++++++++- - 1 file changed, 97 insertions(+), 2 deletions(-) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 40ad8cbd3138..c0f372167557 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -73,7 +73,8 @@ static int unlock_mutex(int mutex, __u32 owner, __u32 *count) - return ret; - } - --static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) -+static int wait_objs(int fd, unsigned long request, __u32 count, -+ const int *objs, __u32 owner, __u32 *index) - { - struct ntsync_wait_args args = {0}; - struct timespec timeout; -@@ -86,11 +87,21 @@ static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *in - args.objs = (uintptr_t)objs; - args.owner = owner; - args.index = 0xdeadbeef; -- ret = ioctl(fd, NTSYNC_IOC_WAIT_ANY, &args); -+ ret = ioctl(fd, request, &args); - *index = args.index; - return ret; - } - -+static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) -+{ -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ANY, count, objs, owner, index); -+} -+ -+static int wait_all(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) -+{ -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ALL, count, objs, owner, index); -+} -+ - TEST(semaphore_state) - { - struct ntsync_sem_args sem_args; -@@ -461,4 +472,88 @@ TEST(test_wait_any) - close(fd); - } - -+TEST(test_wait_all) -+{ -+ struct ntsync_mutex_args mutex_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ __u32 owner, index, count; -+ int objs[2], fd, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 2; -+ sem_args.max = 3; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 0; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ -+ objs[0] = sem_args.sem; -+ objs[1] = mutex_args.mutex; -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ ret = wait_all(fd, 2, objs, 456, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 2, 123); -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_mutex_state(mutex_args.mutex, 2, 123); -+ -+ count = 3; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 2, 3); -+ check_mutex_state(mutex_args.mutex, 3, 123); -+ -+ owner = 123; -+ ret = ioctl(mutex_args.mutex, NTSYNC_IOC_MUTEX_KILL, &owner); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EOWNERDEAD, errno); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 1, 123); -+ -+ /* test waiting on the same object twice */ -+ objs[0] = objs[1] = sem_args.sem; -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(EINVAL, errno); -+ -+ close(sem_args.sem); -+ close(mutex_args.mutex); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0021-[PATCH_v2_22_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ANY..patch" "b/linux-gcc/linux6.8-zen/patches/0021-[PATCH_v2_22_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ANY..patch" deleted file mode 100644 index d813930..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0021-[PATCH_v2_22_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ANY..patch" +++ /dev/null @@ -1,169 +0,0 @@ -Test contended "wait-for-any" waits, to make sure that scheduling and wakeup -logic works correctly. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 150 ++++++++++++++++++ - 1 file changed, 150 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index c0f372167557..993f5db23768 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -556,4 +556,154 @@ TEST(test_wait_all) - close(fd); - } - -+struct wake_args { -+ int fd; -+ int obj; -+}; -+ -+struct wait_args { -+ int fd; -+ unsigned long request; -+ struct ntsync_wait_args *args; -+ int ret; -+ int err; -+}; -+ -+static void *wait_thread(void *arg) -+{ -+ struct wait_args *args = arg; -+ -+ args->ret = ioctl(args->fd, args->request, args->args); -+ args->err = errno; -+ return NULL; -+} -+ -+static __u64 get_abs_timeout(unsigned int ms) -+{ -+ struct timespec timeout; -+ clock_gettime(CLOCK_MONOTONIC, &timeout); -+ return (timeout.tv_sec * 1000000000) + timeout.tv_nsec + (ms * 1000000); -+} -+ -+static int wait_for_thread(pthread_t thread, unsigned int ms) -+{ -+ struct timespec timeout; -+ -+ clock_gettime(CLOCK_REALTIME, &timeout); -+ timeout.tv_nsec += ms * 1000000; -+ timeout.tv_sec += (timeout.tv_nsec / 1000000000); -+ timeout.tv_nsec %= 1000000000; -+ return pthread_timedjoin_np(thread, NULL, &timeout); -+} -+ -+TEST(wake_any) -+{ -+ struct ntsync_mutex_args mutex_args = {0}; -+ struct ntsync_wait_args wait_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ struct wait_args thread_args; -+ int objs[2], fd, ret; -+ __u32 count, index; -+ pthread_t thread; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 0; -+ sem_args.max = 3; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = 1; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ -+ objs[0] = sem_args.sem; -+ objs[1] = mutex_args.mutex; -+ -+ /* test waking the semaphore */ -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.objs = (uintptr_t)objs; -+ wait_args.count = 2; -+ wait_args.owner = 456; -+ wait_args.index = 0xdeadbeef; -+ thread_args.fd = fd; -+ thread_args.args = &wait_args; -+ thread_args.request = NTSYNC_IOC_WAIT_ANY; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ count = 1; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ check_sem_state(sem_args.sem, 0, 3); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(0, wait_args.index); -+ -+ /* test waking the mutex */ -+ -+ /* first grab it again for owner 123 */ -+ ret = wait_any(fd, 1, &mutex_args.mutex, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.owner = 456; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = unlock_mutex(mutex_args.mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, count); -+ -+ ret = pthread_tryjoin_np(thread, NULL); -+ EXPECT_EQ(EBUSY, ret); -+ -+ ret = unlock_mutex(mutex_args.mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, mutex_args.count); -+ check_mutex_state(mutex_args.mutex, 1, 456); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ /* delete an object while it's being waited on */ -+ -+ wait_args.timeout = get_abs_timeout(200); -+ wait_args.owner = 123; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ close(sem_args.sem); -+ close(mutex_args.mutex); -+ -+ ret = wait_for_thread(thread, 200); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(-1, thread_args.ret); -+ EXPECT_EQ(ETIMEDOUT, thread_args.err); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0022-[PATCH_v2_23_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ALL..patch" "b/linux-gcc/linux6.8-zen/patches/0022-[PATCH_v2_23_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ALL..patch" deleted file mode 100644 index 053e2c7..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0022-[PATCH_v2_23_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_WINESYNC_IOC_WAIT_ALL..patch" +++ /dev/null @@ -1,118 +0,0 @@ -Test contended "wait-for-all" waits, to make sure that scheduling and wakeup -logic works correctly, and that the wait only exits once objects are all -simultaneously signaled. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 98 +++++++++++++++++++ - 1 file changed, 98 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 993f5db23768..b77fb0b2c4b1 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -706,4 +706,102 @@ TEST(wake_any) - close(fd); - } - -+TEST(wake_all) -+{ -+ struct ntsync_mutex_args mutex_args = {0}; -+ struct ntsync_wait_args wait_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ struct wait_args thread_args; -+ int objs[2], fd, ret; -+ __u32 count, index; -+ pthread_t thread; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 0; -+ sem_args.max = 3; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ -+ mutex_args.owner = 123; -+ mutex_args.count = 1; -+ mutex_args.mutex = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, mutex_args.mutex); -+ -+ objs[0] = sem_args.sem; -+ objs[1] = mutex_args.mutex; -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.objs = (uintptr_t)objs; -+ wait_args.count = 2; -+ wait_args.owner = 456; -+ thread_args.fd = fd; -+ thread_args.args = &wait_args; -+ thread_args.request = NTSYNC_IOC_WAIT_ALL; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ count = 1; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ -+ ret = pthread_tryjoin_np(thread, NULL); -+ EXPECT_EQ(EBUSY, ret); -+ -+ check_sem_state(sem_args.sem, 1, 3); -+ -+ ret = wait_any(fd, 1, &sem_args.sem, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = unlock_mutex(mutex_args.mutex, 123, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, count); -+ -+ ret = pthread_tryjoin_np(thread, NULL); -+ EXPECT_EQ(EBUSY, ret); -+ -+ check_mutex_state(mutex_args.mutex, 0, 0); -+ -+ count = 2; -+ ret = post_sem(sem_args.sem, &count); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, count); -+ check_sem_state(sem_args.sem, 1, 3); -+ check_mutex_state(mutex_args.mutex, 1, 456); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ -+ /* delete an object while it's being waited on */ -+ -+ wait_args.timeout = get_abs_timeout(200); -+ wait_args.owner = 123; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ close(sem_args.sem); -+ close(mutex_args.mutex); -+ -+ ret = wait_for_thread(thread, 200); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(-1, thread_args.ret); -+ EXPECT_EQ(ETIMEDOUT, thread_args.err); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0023-[PATCH_v2_24_31]_selftests:_ntsync:_Add_some_tests_for\n_manual-reset_event_state..patch" "b/linux-gcc/linux6.8-zen/patches/0023-[PATCH_v2_24_31]_selftests:_ntsync:_Add_some_tests_for\n_manual-reset_event_state..patch" deleted file mode 100644 index ace9ac0..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0023-[PATCH_v2_24_31]_selftests:_ntsync:_Add_some_tests_for\n_manual-reset_event_state..patch" +++ /dev/null @@ -1,118 +0,0 @@ -Test event-specific ioctls NTSYNC_IOC_EVENT_SET, NTSYNC_IOC_EVENT_RESET, -NTSYNC_IOC_EVENT_PULSE, NTSYNC_IOC_EVENT_READ for manual-reset events, and -waiting on manual-reset events. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 89 +++++++++++++++++++ - 1 file changed, 89 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index b77fb0b2c4b1..b6481c2b85cc 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -73,6 +73,27 @@ static int unlock_mutex(int mutex, __u32 owner, __u32 *count) - return ret; - } - -+static int read_event_state(int event, __u32 *signaled, __u32 *manual) -+{ -+ struct ntsync_event_args args; -+ int ret; -+ -+ memset(&args, 0xcc, sizeof(args)); -+ ret = ioctl(event, NTSYNC_IOC_EVENT_READ, &args); -+ *signaled = args.signaled; -+ *manual = args.manual; -+ return ret; -+} -+ -+#define check_event_state(event, signaled, manual) \ -+ ({ \ -+ __u32 __signaled, __manual; \ -+ int ret = read_event_state((event), &__signaled, &__manual); \ -+ EXPECT_EQ(0, ret); \ -+ EXPECT_EQ((signaled), __signaled); \ -+ EXPECT_EQ((manual), __manual); \ -+ }) -+ - static int wait_objs(int fd, unsigned long request, __u32 count, - const int *objs, __u32 owner, __u32 *index) - { -@@ -353,6 +374,74 @@ TEST(mutex_state) - close(fd); - } - -+TEST(manual_event_state) -+{ -+ struct ntsync_event_args event_args; -+ __u32 index, signaled; -+ int fd, event, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ event_args.manual = 1; -+ event_args.signaled = 0; -+ event_args.event = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, event_args.event); -+ event = event_args.event; -+ check_event_state(event, 0, 1); -+ -+ signaled = 0xdeadbeef; -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 1, 1); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 1, 1); -+ -+ ret = wait_any(fd, 1, &event, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_event_state(event, 1, 1); -+ -+ signaled = 0xdeadbeef; -+ ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 0, 1); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 0, 1); -+ -+ ret = wait_any(fd, 1, &event, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 0, 1); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 0, 1); -+ -+ close(event); -+ -+ close(fd); -+} -+ - TEST(test_wait_any) - { - int objs[NTSYNC_MAX_WAIT_COUNT + 1], fd, ret; --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0024-[PATCH_v2_25_31]_selftests:_ntsync:_Add_some_tests_for_auto-reset\n_event_state..patch" "b/linux-gcc/linux6.8-zen/patches/0024-[PATCH_v2_25_31]_selftests:_ntsync:_Add_some_tests_for_auto-reset\n_event_state..patch" deleted file mode 100644 index 3989a16..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0024-[PATCH_v2_25_31]_selftests:_ntsync:_Add_some_tests_for_auto-reset\n_event_state..patch" +++ /dev/null @@ -1,81 +0,0 @@ -Test event-specific ioctls NTSYNC_IOC_EVENT_SET, NTSYNC_IOC_EVENT_RESET, -NTSYNC_IOC_EVENT_PULSE, NTSYNC_IOC_EVENT_READ for auto-reset events, and -waiting on auto-reset events. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 59 +++++++++++++++++++ - 1 file changed, 59 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index b6481c2b85cc..12ccb4ec28e4 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -442,6 +442,65 @@ TEST(manual_event_state) - close(fd); - } - -+TEST(auto_event_state) -+{ -+ struct ntsync_event_args event_args; -+ __u32 index, signaled; -+ int fd, event, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ event_args.manual = 0; -+ event_args.signaled = 1; -+ event_args.event = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, event_args.event); -+ event = event_args.event; -+ -+ check_event_state(event, 1, 0); -+ -+ signaled = 0xdeadbeef; -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 1, 0); -+ -+ ret = wait_any(fd, 1, &event, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_event_state(event, 0, 0); -+ -+ signaled = 0xdeadbeef; -+ ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 0, 0); -+ -+ ret = wait_any(fd, 1, &event, 123, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ check_event_state(event, 0, 0); -+ -+ ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event, 0, 0); -+ -+ close(event); -+ -+ close(fd); -+} -+ - TEST(test_wait_any) - { - int objs[NTSYNC_MAX_WAIT_COUNT + 1], fd, ret; --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0025-[PATCH_v2_26_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_events..patch" "b/linux-gcc/linux6.8-zen/patches/0025-[PATCH_v2_26_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_events..patch" deleted file mode 100644 index 832a88f..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0025-[PATCH_v2_26_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_with_events..patch" +++ /dev/null @@ -1,259 +0,0 @@ -Expand the contended wait tests, which previously only covered events and -semaphores, to cover events as well. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 151 +++++++++++++++++- - 1 file changed, 147 insertions(+), 4 deletions(-) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 12ccb4ec28e4..5d17eff6a370 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -622,6 +622,7 @@ TEST(test_wait_any) - - TEST(test_wait_all) - { -+ struct ntsync_event_args event_args = {0}; - struct ntsync_mutex_args mutex_args = {0}; - struct ntsync_sem_args sem_args = {0}; - __u32 owner, index, count; -@@ -644,6 +645,11 @@ TEST(test_wait_all) - EXPECT_EQ(0, ret); - EXPECT_NE(0xdeadbeef, mutex_args.mutex); - -+ event_args.manual = true; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ - objs[0] = sem_args.sem; - objs[1] = mutex_args.mutex; - -@@ -692,6 +698,14 @@ TEST(test_wait_all) - check_sem_state(sem_args.sem, 1, 3); - check_mutex_state(mutex_args.mutex, 1, 123); - -+ objs[0] = sem_args.sem; -+ objs[1] = event_args.event; -+ ret = wait_all(fd, 2, objs, 123, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ check_sem_state(sem_args.sem, 0, 3); -+ check_event_state(event_args.event, 1, 1); -+ - /* test waiting on the same object twice */ - objs[0] = objs[1] = sem_args.sem; - ret = wait_all(fd, 2, objs, 123, &index); -@@ -700,6 +714,7 @@ TEST(test_wait_all) - - close(sem_args.sem); - close(mutex_args.mutex); -+ close(event_args.event); - - close(fd); - } -@@ -746,12 +761,13 @@ static int wait_for_thread(pthread_t thread, unsigned int ms) - - TEST(wake_any) - { -+ struct ntsync_event_args event_args = {0}; - struct ntsync_mutex_args mutex_args = {0}; - struct ntsync_wait_args wait_args = {0}; - struct ntsync_sem_args sem_args = {0}; - struct wait_args thread_args; -+ __u32 count, index, signaled; - int objs[2], fd, ret; -- __u32 count, index; - pthread_t thread; - - fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -@@ -833,10 +849,101 @@ TEST(wake_any) - EXPECT_EQ(0, thread_args.ret); - EXPECT_EQ(1, wait_args.index); - -+ /* test waking events */ -+ -+ event_args.manual = false; -+ event_args.signaled = false; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ objs[1] = event_args.event; -+ wait_args.timeout = get_abs_timeout(1000); -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event_args.event, 0, 0); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event_args.event, 0, 0); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ close(event_args.event); -+ -+ event_args.manual = true; -+ event_args.signaled = false; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ objs[1] = event_args.event; -+ wait_args.timeout = get_abs_timeout(1000); -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event_args.event, 1, 1); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_PULSE, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ check_event_state(event_args.event, 0, 1); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(1, wait_args.index); -+ -+ close(event_args.event); -+ - /* delete an object while it's being waited on */ - - wait_args.timeout = get_abs_timeout(200); - wait_args.owner = 123; -+ objs[1] = mutex_args.mutex; - ret = pthread_create(&thread, NULL, wait_thread, &thread_args); - EXPECT_EQ(0, ret); - -@@ -856,12 +963,14 @@ TEST(wake_any) - - TEST(wake_all) - { -+ struct ntsync_event_args manual_event_args = {0}; -+ struct ntsync_event_args auto_event_args = {0}; - struct ntsync_mutex_args mutex_args = {0}; - struct ntsync_wait_args wait_args = {0}; - struct ntsync_sem_args sem_args = {0}; - struct wait_args thread_args; -- int objs[2], fd, ret; -- __u32 count, index; -+ __u32 count, index, signaled; -+ int objs[4], fd, ret; - pthread_t thread; - - fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -@@ -881,12 +990,24 @@ TEST(wake_all) - EXPECT_EQ(0, ret); - EXPECT_NE(0xdeadbeef, mutex_args.mutex); - -+ manual_event_args.manual = true; -+ manual_event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &manual_event_args); -+ EXPECT_EQ(0, ret); -+ -+ auto_event_args.manual = false; -+ auto_event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &auto_event_args); -+ EXPECT_EQ(0, ret); -+ - objs[0] = sem_args.sem; - objs[1] = mutex_args.mutex; -+ objs[2] = manual_event_args.event; -+ objs[3] = auto_event_args.event; - - wait_args.timeout = get_abs_timeout(1000); - wait_args.objs = (uintptr_t)objs; -- wait_args.count = 2; -+ wait_args.count = 4; - wait_args.owner = 456; - thread_args.fd = fd; - thread_args.args = &wait_args; -@@ -920,12 +1041,32 @@ TEST(wake_all) - - check_mutex_state(mutex_args.mutex, 0, 0); - -+ ret = ioctl(manual_event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ - count = 2; - ret = post_sem(sem_args.sem, &count); - EXPECT_EQ(0, ret); - EXPECT_EQ(0, count); -+ check_sem_state(sem_args.sem, 2, 3); -+ -+ ret = ioctl(auto_event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, signaled); -+ -+ ret = ioctl(manual_event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ -+ ret = ioctl(auto_event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, signaled); -+ - check_sem_state(sem_args.sem, 1, 3); - check_mutex_state(mutex_args.mutex, 1, 456); -+ check_event_state(manual_event_args.event, 1, 1); -+ check_event_state(auto_event_args.event, 0, 0); - - ret = wait_for_thread(thread, 100); - EXPECT_EQ(0, ret); -@@ -943,6 +1084,8 @@ TEST(wake_all) - - close(sem_args.sem); - close(mutex_args.mutex); -+ close(manual_event_args.event); -+ close(auto_event_args.event); - - ret = wait_for_thread(thread, 200); - EXPECT_EQ(0, ret); --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0026-[PATCH_v2_27_31]_selftests:_ntsync:_Add_tests_for_alertable_waits..patch b/linux-gcc/linux6.8-zen/patches/0026-[PATCH_v2_27_31]_selftests:_ntsync:_Add_tests_for_alertable_waits..patch deleted file mode 100644 index b8f967b..0000000 --- a/linux-gcc/linux6.8-zen/patches/0026-[PATCH_v2_27_31]_selftests:_ntsync:_Add_tests_for_alertable_waits..patch +++ /dev/null @@ -1,223 +0,0 @@ -Test the "alert" functionality of NTSYNC_IOC_WAIT_ALL and NTSYNC_IOC_WAIT_ANY, -when a wait is woken with an alert and when it is woken by an object. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 179 +++++++++++++++++- - 1 file changed, 176 insertions(+), 3 deletions(-) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 5d17eff6a370..5465a16d38b3 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -95,7 +95,7 @@ static int read_event_state(int event, __u32 *signaled, __u32 *manual) - }) - - static int wait_objs(int fd, unsigned long request, __u32 count, -- const int *objs, __u32 owner, __u32 *index) -+ const int *objs, __u32 owner, int alert, __u32 *index) - { - struct ntsync_wait_args args = {0}; - struct timespec timeout; -@@ -108,6 +108,7 @@ static int wait_objs(int fd, unsigned long request, __u32 count, - args.objs = (uintptr_t)objs; - args.owner = owner; - args.index = 0xdeadbeef; -+ args.alert = alert; - ret = ioctl(fd, request, &args); - *index = args.index; - return ret; -@@ -115,12 +116,26 @@ static int wait_objs(int fd, unsigned long request, __u32 count, - - static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) - { -- return wait_objs(fd, NTSYNC_IOC_WAIT_ANY, count, objs, owner, index); -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ANY, count, objs, owner, 0, index); - } - - static int wait_all(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index) - { -- return wait_objs(fd, NTSYNC_IOC_WAIT_ALL, count, objs, owner, index); -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ALL, count, objs, owner, 0, index); -+} -+ -+static int wait_any_alert(int fd, __u32 count, const int *objs, -+ __u32 owner, int alert, __u32 *index) -+{ -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ANY, -+ count, objs, owner, alert, index); -+} -+ -+static int wait_all_alert(int fd, __u32 count, const int *objs, -+ __u32 owner, int alert, __u32 *index) -+{ -+ return wait_objs(fd, NTSYNC_IOC_WAIT_ALL, -+ count, objs, owner, alert, index); - } - - TEST(semaphore_state) -@@ -1095,4 +1110,162 @@ TEST(wake_all) - close(fd); - } - -+TEST(alert_any) -+{ -+ struct ntsync_event_args event_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ __u32 index, count, signaled; -+ int objs[2], fd, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 0; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ objs[0] = sem_args.sem; -+ -+ sem_args.count = 1; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ objs[1] = sem_args.sem; -+ -+ event_args.manual = true; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any_alert(fd, 0, NULL, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any_alert(fd, 0, NULL, 123, event_args.event, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(1, index); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, index); -+ -+ close(event_args.event); -+ -+ /* test with an auto-reset event */ -+ -+ event_args.manual = false; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ count = 1; -+ ret = post_sem(objs[0], &count); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, index); -+ -+ ret = wait_any_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ close(event_args.event); -+ -+ close(objs[0]); -+ close(objs[1]); -+ -+ close(fd); -+} -+ -+TEST(alert_all) -+{ -+ struct ntsync_event_args event_args = {0}; -+ struct ntsync_sem_args sem_args = {0}; -+ __u32 index, count, signaled; -+ int objs[2], fd, ret; -+ -+ fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, fd); -+ -+ sem_args.count = 2; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ objs[0] = sem_args.sem; -+ -+ sem_args.count = 1; -+ sem_args.max = 2; -+ sem_args.sem = 0xdeadbeef; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args); -+ EXPECT_EQ(0, ret); -+ EXPECT_NE(0xdeadbeef, sem_args.sem); -+ objs[1] = sem_args.sem; -+ -+ event_args.manual = true; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, index); -+ -+ close(event_args.event); -+ -+ /* test with an auto-reset event */ -+ -+ event_args.manual = false; -+ event_args.signaled = true; -+ ret = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ -+ count = 2; -+ ret = post_sem(objs[1], &count); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, index); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(2, index); -+ -+ ret = wait_all_alert(fd, 2, objs, 123, event_args.event, &index); -+ EXPECT_EQ(-1, ret); -+ EXPECT_EQ(ETIMEDOUT, errno); -+ -+ close(event_args.event); -+ -+ close(objs[0]); -+ close(objs[1]); -+ -+ close(fd); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0027-[PATCH_v2_28_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_via_alerts..patch" "b/linux-gcc/linux6.8-zen/patches/0027-[PATCH_v2_28_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_via_alerts..patch" deleted file mode 100644 index 5e0734b..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0027-[PATCH_v2_28_31]_selftests:_ntsync:_Add_some_tests_for_wakeup\n_signaling_via_alerts..patch" +++ /dev/null @@ -1,110 +0,0 @@ -Expand the alert tests to cover alerting a thread mid-wait, to test that the -relevant scheduling logic works correctly. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 62 +++++++++++++++++++ - 1 file changed, 62 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 5465a16d38b3..968874d7e325 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -1113,9 +1113,12 @@ TEST(wake_all) - TEST(alert_any) - { - struct ntsync_event_args event_args = {0}; -+ struct ntsync_wait_args wait_args = {0}; - struct ntsync_sem_args sem_args = {0}; - __u32 index, count, signaled; -+ struct wait_args thread_args; - int objs[2], fd, ret; -+ pthread_t thread; - - fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); - ASSERT_LE(0, fd); -@@ -1163,6 +1166,34 @@ TEST(alert_any) - EXPECT_EQ(0, ret); - EXPECT_EQ(2, index); - -+ /* test wakeup via alert */ -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.objs = (uintptr_t)objs; -+ wait_args.count = 2; -+ wait_args.owner = 123; -+ wait_args.index = 0xdeadbeef; -+ wait_args.alert = event_args.event; -+ thread_args.fd = fd; -+ thread_args.args = &wait_args; -+ thread_args.request = NTSYNC_IOC_WAIT_ANY; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(2, wait_args.index); -+ - close(event_args.event); - - /* test with an auto-reset event */ -@@ -1199,9 +1230,12 @@ TEST(alert_any) - TEST(alert_all) - { - struct ntsync_event_args event_args = {0}; -+ struct ntsync_wait_args wait_args = {0}; - struct ntsync_sem_args sem_args = {0}; -+ struct wait_args thread_args; - __u32 index, count, signaled; - int objs[2], fd, ret; -+ pthread_t thread; - - fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); - ASSERT_LE(0, fd); -@@ -1235,6 +1269,34 @@ TEST(alert_all) - EXPECT_EQ(0, ret); - EXPECT_EQ(2, index); - -+ /* test wakeup via alert */ -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_RESET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ wait_args.timeout = get_abs_timeout(1000); -+ wait_args.objs = (uintptr_t)objs; -+ wait_args.count = 2; -+ wait_args.owner = 123; -+ wait_args.index = 0xdeadbeef; -+ wait_args.alert = event_args.event; -+ thread_args.fd = fd; -+ thread_args.args = &wait_args; -+ thread_args.request = NTSYNC_IOC_WAIT_ALL; -+ ret = pthread_create(&thread, NULL, wait_thread, &thread_args); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(ETIMEDOUT, ret); -+ -+ ret = ioctl(event_args.event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ ret = wait_for_thread(thread, 100); -+ EXPECT_EQ(0, ret); -+ EXPECT_EQ(0, thread_args.ret); -+ EXPECT_EQ(2, wait_args.index); -+ - close(event_args.event); - - /* test with an auto-reset event */ --- -2.43.0 diff --git "a/linux-gcc/linux6.8-zen/patches/0028-[PATCH_v2_29_31]_selftests:_ntsync:_Add_a_stress_test_for\n_contended_waits..patch" "b/linux-gcc/linux6.8-zen/patches/0028-[PATCH_v2_29_31]_selftests:_ntsync:_Add_a_stress_test_for\n_contended_waits..patch" deleted file mode 100644 index 5fcc536..0000000 --- "a/linux-gcc/linux6.8-zen/patches/0028-[PATCH_v2_29_31]_selftests:_ntsync:_Add_a_stress_test_for\n_contended_waits..patch" +++ /dev/null @@ -1,97 +0,0 @@ -Test a more realistic usage pattern, and one with heavy contention, in order to -actually exercise ntsync's internal synchronization. - -This test has several threads in a tight loop acquiring a mutex, modifying some -shared data, and then releasing the mutex. At the end we check if the data is -consistent. - -Signed-off-by: Elizabeth Figura ---- - .../testing/selftests/drivers/ntsync/ntsync.c | 74 +++++++++++++++++++ - 1 file changed, 74 insertions(+) - -diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c -index 968874d7e325..5fa2c9a0768c 100644 ---- a/tools/testing/selftests/drivers/ntsync/ntsync.c -+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c -@@ -1330,4 +1330,78 @@ TEST(alert_all) - close(fd); - } - -+#define STRESS_LOOPS 10000 -+#define STRESS_THREADS 4 -+ -+static unsigned int stress_counter; -+static int stress_device, stress_start_event, stress_mutex; -+ -+static void *stress_thread(void *arg) -+{ -+ struct ntsync_wait_args wait_args = {0}; -+ __u32 index, count, i; -+ int ret; -+ -+ wait_args.timeout = UINT64_MAX; -+ wait_args.count = 1; -+ wait_args.objs = (uintptr_t)&stress_start_event; -+ wait_args.owner = gettid(); -+ wait_args.index = 0xdeadbeef; -+ -+ ioctl(stress_device, NTSYNC_IOC_WAIT_ANY, &wait_args); -+ -+ wait_args.objs = (uintptr_t)&stress_mutex; -+ -+ for (i = 0; i < STRESS_LOOPS; ++i) { -+ ioctl(stress_device, NTSYNC_IOC_WAIT_ANY, &wait_args); -+ -+ ++stress_counter; -+ -+ unlock_mutex(stress_mutex, wait_args.owner, &count); -+ } -+ -+ return NULL; -+} -+ -+TEST(stress_wait) -+{ -+ struct ntsync_event_args event_args; -+ struct ntsync_mutex_args mutex_args; -+ pthread_t threads[STRESS_THREADS]; -+ __u32 signaled, i; -+ int ret; -+ -+ stress_device = open("/dev/ntsync", O_CLOEXEC | O_RDONLY); -+ ASSERT_LE(0, stress_device); -+ -+ mutex_args.owner = 0; -+ mutex_args.count = 0; -+ ret = ioctl(stress_device, NTSYNC_IOC_CREATE_MUTEX, &mutex_args); -+ EXPECT_EQ(0, ret); -+ stress_mutex = mutex_args.mutex; -+ -+ event_args.manual = 1; -+ event_args.signaled = 0; -+ ret = ioctl(stress_device, NTSYNC_IOC_CREATE_EVENT, &event_args); -+ EXPECT_EQ(0, ret); -+ stress_start_event = event_args.event; -+ -+ for (i = 0; i < STRESS_THREADS; ++i) -+ pthread_create(&threads[i], NULL, stress_thread, NULL); -+ -+ ret = ioctl(stress_start_event, NTSYNC_IOC_EVENT_SET, &signaled); -+ EXPECT_EQ(0, ret); -+ -+ for (i = 0; i < STRESS_THREADS; ++i) { -+ ret = pthread_join(threads[i], NULL); -+ EXPECT_EQ(0, ret); -+ } -+ -+ EXPECT_EQ(STRESS_LOOPS * STRESS_THREADS, stress_counter); -+ -+ close(stress_start_event); -+ close(stress_mutex); -+ close(stress_device); -+} -+ - TEST_HARNESS_MAIN --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/patches/0029-[PATCH_v2_30_31]_maintainers:_Add_an_entry_for_ntsync..patch b/linux-gcc/linux6.8-zen/patches/0029-[PATCH_v2_30_31]_maintainers:_Add_an_entry_for_ntsync..patch deleted file mode 100644 index f7e2bd6..0000000 --- a/linux-gcc/linux6.8-zen/patches/0029-[PATCH_v2_30_31]_maintainers:_Add_an_entry_for_ntsync..patch +++ /dev/null @@ -1,29 +0,0 @@ -Add myself as maintainer, supported by CodeWeavers. - -Signed-off-by: Elizabeth Figura ---- - MAINTAINERS | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/MAINTAINERS b/MAINTAINERS -index 9ed4d3868539..d83dd35d9f73 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -15595,6 +15595,15 @@ T: git https://github.com/Paragon-Software-Group/linux-ntfs3.git - F: Documentation/filesystems/ntfs3.rst - F: fs/ntfs3/ - -+NTSYNC SYNCHRONIZATION PRIMITIVE DRIVER -+M: Elizabeth Figura -+L: wine-devel@winehq.org -+S: Supported -+F: Documentation/userspace-api/ntsync.rst -+F: drivers/misc/ntsync.c -+F: include/uapi/linux/ntsync.h -+F: tools/testing/selftests/drivers/ntsync/ -+ - NUBUS SUBSYSTEM - M: Finn Thain - L: linux-m68k@lists.linux-m68k.org --- -2.43.0 diff --git a/linux-gcc/linux6.8-zen/template b/linux-gcc/linux6.8-zen/template index 08f5693..000b634 100644 --- a/linux-gcc/linux6.8-zen/template +++ b/linux-gcc/linux6.8-zen/template @@ -1,5 +1,5 @@ pkgname=linux6.8-zen -version=6.8.6 +version=6.8.7 revision=1 zen=1 python_version=3 @@ -8,7 +8,7 @@ maintainer="Wizzard " license="GPL-2.0-only" homepage="https://github.com/zen-kernel/zen-kernel" distfiles="https://github.com/zen-kernel/zen-kernel/archive/refs/tags/v${version}-zen${zen}.tar.gz" -checksum="a6f2cd6b3ed6555161b688d41d04275c2bf05e893778a8e5b2c52a3ff627db1f" +checksum="5ab6ad1d26925f02a74b41d485e5faf25056efec123d0a1433aa3a4108534aae" archs="x86_64* i686* ppc* aarch64*" patch_args="-Np1"