17f853a25SElizabeth Figura // SPDX-License-Identifier: GPL-2.0-or-later
27f853a25SElizabeth Figura /*
37f853a25SElizabeth Figura  * Various unit tests for the "ntsync" synchronization primitive driver.
47f853a25SElizabeth Figura  *
57f853a25SElizabeth Figura  * Copyright (C) 2021-2022 Elizabeth Figura <[email protected]>
67f853a25SElizabeth Figura  */
77f853a25SElizabeth Figura 
87f853a25SElizabeth Figura #define _GNU_SOURCE
97f853a25SElizabeth Figura #include <sys/ioctl.h>
107f853a25SElizabeth Figura #include <sys/stat.h>
117f853a25SElizabeth Figura #include <fcntl.h>
127f853a25SElizabeth Figura #include <time.h>
137f853a25SElizabeth Figura #include <pthread.h>
147f853a25SElizabeth Figura #include <linux/ntsync.h>
157f853a25SElizabeth Figura #include "../../kselftest_harness.h"
167f853a25SElizabeth Figura 
read_sem_state(int sem,__u32 * count,__u32 * max)177f853a25SElizabeth Figura static int read_sem_state(int sem, __u32 *count, __u32 *max)
187f853a25SElizabeth Figura {
197f853a25SElizabeth Figura 	struct ntsync_sem_args args;
207f853a25SElizabeth Figura 	int ret;
217f853a25SElizabeth Figura 
227f853a25SElizabeth Figura 	memset(&args, 0xcc, sizeof(args));
237f853a25SElizabeth Figura 	ret = ioctl(sem, NTSYNC_IOC_SEM_READ, &args);
247f853a25SElizabeth Figura 	*count = args.count;
257f853a25SElizabeth Figura 	*max = args.max;
267f853a25SElizabeth Figura 	return ret;
277f853a25SElizabeth Figura }
287f853a25SElizabeth Figura 
297f853a25SElizabeth Figura #define check_sem_state(sem, count, max) \
307f853a25SElizabeth Figura 	({ \
317f853a25SElizabeth Figura 		__u32 __count, __max; \
327f853a25SElizabeth Figura 		int ret = read_sem_state((sem), &__count, &__max); \
337f853a25SElizabeth Figura 		EXPECT_EQ(0, ret); \
347f853a25SElizabeth Figura 		EXPECT_EQ((count), __count); \
357f853a25SElizabeth Figura 		EXPECT_EQ((max), __max); \
367f853a25SElizabeth Figura 	})
377f853a25SElizabeth Figura 
release_sem(int sem,__u32 * count)387f853a25SElizabeth Figura static int release_sem(int sem, __u32 *count)
397f853a25SElizabeth Figura {
407f853a25SElizabeth Figura 	return ioctl(sem, NTSYNC_IOC_SEM_RELEASE, count);
417f853a25SElizabeth Figura }
427f853a25SElizabeth Figura 
read_mutex_state(int mutex,__u32 * count,__u32 * owner)43ae071aefSElizabeth Figura static int read_mutex_state(int mutex, __u32 *count, __u32 *owner)
44ae071aefSElizabeth Figura {
45ae071aefSElizabeth Figura 	struct ntsync_mutex_args args;
46ae071aefSElizabeth Figura 	int ret;
47ae071aefSElizabeth Figura 
48ae071aefSElizabeth Figura 	memset(&args, 0xcc, sizeof(args));
49ae071aefSElizabeth Figura 	ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &args);
50ae071aefSElizabeth Figura 	*count = args.count;
51ae071aefSElizabeth Figura 	*owner = args.owner;
52ae071aefSElizabeth Figura 	return ret;
53ae071aefSElizabeth Figura }
54ae071aefSElizabeth Figura 
55ae071aefSElizabeth Figura #define check_mutex_state(mutex, count, owner) \
56ae071aefSElizabeth Figura 	({ \
57ae071aefSElizabeth Figura 		__u32 __count, __owner; \
58ae071aefSElizabeth Figura 		int ret = read_mutex_state((mutex), &__count, &__owner); \
59ae071aefSElizabeth Figura 		EXPECT_EQ(0, ret); \
60ae071aefSElizabeth Figura 		EXPECT_EQ((count), __count); \
61ae071aefSElizabeth Figura 		EXPECT_EQ((owner), __owner); \
62ae071aefSElizabeth Figura 	})
63ae071aefSElizabeth Figura 
unlock_mutex(int mutex,__u32 owner,__u32 * count)64ae071aefSElizabeth Figura static int unlock_mutex(int mutex, __u32 owner, __u32 *count)
65ae071aefSElizabeth Figura {
66ae071aefSElizabeth Figura 	struct ntsync_mutex_args args;
67ae071aefSElizabeth Figura 	int ret;
68ae071aefSElizabeth Figura 
69ae071aefSElizabeth Figura 	args.owner = owner;
70ae071aefSElizabeth Figura 	args.count = 0xdeadbeef;
71ae071aefSElizabeth Figura 	ret = ioctl(mutex, NTSYNC_IOC_MUTEX_UNLOCK, &args);
72ae071aefSElizabeth Figura 	*count = args.count;
73ae071aefSElizabeth Figura 	return ret;
74ae071aefSElizabeth Figura }
75ae071aefSElizabeth Figura 
read_event_state(int event,__u32 * signaled,__u32 * manual)76d2083b5fSElizabeth Figura static int read_event_state(int event, __u32 *signaled, __u32 *manual)
77d2083b5fSElizabeth Figura {
78d2083b5fSElizabeth Figura 	struct ntsync_event_args args;
79d2083b5fSElizabeth Figura 	int ret;
80d2083b5fSElizabeth Figura 
81d2083b5fSElizabeth Figura 	memset(&args, 0xcc, sizeof(args));
82d2083b5fSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_READ, &args);
83d2083b5fSElizabeth Figura 	*signaled = args.signaled;
84d2083b5fSElizabeth Figura 	*manual = args.manual;
85d2083b5fSElizabeth Figura 	return ret;
86d2083b5fSElizabeth Figura }
87d2083b5fSElizabeth Figura 
88d2083b5fSElizabeth Figura #define check_event_state(event, signaled, manual) \
89d2083b5fSElizabeth Figura 	({ \
90d2083b5fSElizabeth Figura 		__u32 __signaled, __manual; \
91d2083b5fSElizabeth Figura 		int ret = read_event_state((event), &__signaled, &__manual); \
92d2083b5fSElizabeth Figura 		EXPECT_EQ(0, ret); \
93d2083b5fSElizabeth Figura 		EXPECT_EQ((signaled), __signaled); \
94d2083b5fSElizabeth Figura 		EXPECT_EQ((manual), __manual); \
95d2083b5fSElizabeth Figura 	})
96d2083b5fSElizabeth Figura 
wait_objs(int fd,unsigned long request,__u32 count,const int * objs,__u32 owner,int alert,__u32 * index)97d168f689SElizabeth Figura static int wait_objs(int fd, unsigned long request, __u32 count,
98dd914e0dSElizabeth Figura 		     const int *objs, __u32 owner, int alert, __u32 *index)
997f853a25SElizabeth Figura {
1007f853a25SElizabeth Figura 	struct ntsync_wait_args args = {0};
1017f853a25SElizabeth Figura 	struct timespec timeout;
1027f853a25SElizabeth Figura 	int ret;
1037f853a25SElizabeth Figura 
1047f853a25SElizabeth Figura 	clock_gettime(CLOCK_MONOTONIC, &timeout);
1057f853a25SElizabeth Figura 
1067f853a25SElizabeth Figura 	args.timeout = timeout.tv_sec * 1000000000 + timeout.tv_nsec;
1077f853a25SElizabeth Figura 	args.count = count;
1087f853a25SElizabeth Figura 	args.objs = (uintptr_t)objs;
1097f853a25SElizabeth Figura 	args.owner = owner;
1107f853a25SElizabeth Figura 	args.index = 0xdeadbeef;
111dd914e0dSElizabeth Figura 	args.alert = alert;
112d168f689SElizabeth Figura 	ret = ioctl(fd, request, &args);
1137f853a25SElizabeth Figura 	*index = args.index;
1147f853a25SElizabeth Figura 	return ret;
1157f853a25SElizabeth Figura }
1167f853a25SElizabeth Figura 
wait_any(int fd,__u32 count,const int * objs,__u32 owner,__u32 * index)117d168f689SElizabeth Figura static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index)
118d168f689SElizabeth Figura {
119dd914e0dSElizabeth Figura 	return wait_objs(fd, NTSYNC_IOC_WAIT_ANY, count, objs, owner, 0, index);
120d168f689SElizabeth Figura }
121d168f689SElizabeth Figura 
wait_all(int fd,__u32 count,const int * objs,__u32 owner,__u32 * index)122d168f689SElizabeth Figura static int wait_all(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index)
123d168f689SElizabeth Figura {
124dd914e0dSElizabeth Figura 	return wait_objs(fd, NTSYNC_IOC_WAIT_ALL, count, objs, owner, 0, index);
125dd914e0dSElizabeth Figura }
126dd914e0dSElizabeth Figura 
wait_any_alert(int fd,__u32 count,const int * objs,__u32 owner,int alert,__u32 * index)127dd914e0dSElizabeth Figura static int wait_any_alert(int fd, __u32 count, const int *objs,
128dd914e0dSElizabeth Figura 			  __u32 owner, int alert, __u32 *index)
129dd914e0dSElizabeth Figura {
130dd914e0dSElizabeth Figura 	return wait_objs(fd, NTSYNC_IOC_WAIT_ANY,
131dd914e0dSElizabeth Figura 			 count, objs, owner, alert, index);
132dd914e0dSElizabeth Figura }
133dd914e0dSElizabeth Figura 
wait_all_alert(int fd,__u32 count,const int * objs,__u32 owner,int alert,__u32 * index)134dd914e0dSElizabeth Figura static int wait_all_alert(int fd, __u32 count, const int *objs,
135dd914e0dSElizabeth Figura 			  __u32 owner, int alert, __u32 *index)
136dd914e0dSElizabeth Figura {
137dd914e0dSElizabeth Figura 	return wait_objs(fd, NTSYNC_IOC_WAIT_ALL,
138dd914e0dSElizabeth Figura 			 count, objs, owner, alert, index);
139d168f689SElizabeth Figura }
140d168f689SElizabeth Figura 
TEST(semaphore_state)1417f853a25SElizabeth Figura TEST(semaphore_state)
1427f853a25SElizabeth Figura {
1437f853a25SElizabeth Figura 	struct ntsync_sem_args sem_args;
1447f853a25SElizabeth Figura 	struct timespec timeout;
1457f853a25SElizabeth Figura 	__u32 count, index;
1467f853a25SElizabeth Figura 	int fd, ret, sem;
1477f853a25SElizabeth Figura 
1487f853a25SElizabeth Figura 	clock_gettime(CLOCK_MONOTONIC, &timeout);
1497f853a25SElizabeth Figura 
1507f853a25SElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
1517f853a25SElizabeth Figura 	ASSERT_LE(0, fd);
1527f853a25SElizabeth Figura 
1537f853a25SElizabeth Figura 	sem_args.count = 3;
1547f853a25SElizabeth Figura 	sem_args.max = 2;
1557f853a25SElizabeth Figura 	sem = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
1567f853a25SElizabeth Figura 	EXPECT_EQ(-1, sem);
1577f853a25SElizabeth Figura 	EXPECT_EQ(EINVAL, errno);
1587f853a25SElizabeth Figura 
1597f853a25SElizabeth Figura 	sem_args.count = 2;
1607f853a25SElizabeth Figura 	sem_args.max = 2;
1617f853a25SElizabeth Figura 	sem = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
1627f853a25SElizabeth Figura 	EXPECT_LE(0, sem);
1637f853a25SElizabeth Figura 	check_sem_state(sem, 2, 2);
1647f853a25SElizabeth Figura 
1657f853a25SElizabeth Figura 	count = 0;
1667f853a25SElizabeth Figura 	ret = release_sem(sem, &count);
1677f853a25SElizabeth Figura 	EXPECT_EQ(0, ret);
1687f853a25SElizabeth Figura 	EXPECT_EQ(2, count);
1697f853a25SElizabeth Figura 	check_sem_state(sem, 2, 2);
1707f853a25SElizabeth Figura 
1717f853a25SElizabeth Figura 	count = 1;
1727f853a25SElizabeth Figura 	ret = release_sem(sem, &count);
1737f853a25SElizabeth Figura 	EXPECT_EQ(-1, ret);
1747f853a25SElizabeth Figura 	EXPECT_EQ(EOVERFLOW, errno);
1757f853a25SElizabeth Figura 	check_sem_state(sem, 2, 2);
1767f853a25SElizabeth Figura 
1777f853a25SElizabeth Figura 	ret = wait_any(fd, 1, &sem, 123, &index);
1787f853a25SElizabeth Figura 	EXPECT_EQ(0, ret);
1797f853a25SElizabeth Figura 	EXPECT_EQ(0, index);
1807f853a25SElizabeth Figura 	check_sem_state(sem, 1, 2);
1817f853a25SElizabeth Figura 
1827f853a25SElizabeth Figura 	ret = wait_any(fd, 1, &sem, 123, &index);
1837f853a25SElizabeth Figura 	EXPECT_EQ(0, ret);
1847f853a25SElizabeth Figura 	EXPECT_EQ(0, index);
1857f853a25SElizabeth Figura 	check_sem_state(sem, 0, 2);
1867f853a25SElizabeth Figura 
1877f853a25SElizabeth Figura 	ret = wait_any(fd, 1, &sem, 123, &index);
1887f853a25SElizabeth Figura 	EXPECT_EQ(-1, ret);
1897f853a25SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
1907f853a25SElizabeth Figura 
1917f853a25SElizabeth Figura 	count = 3;
1927f853a25SElizabeth Figura 	ret = release_sem(sem, &count);
1937f853a25SElizabeth Figura 	EXPECT_EQ(-1, ret);
1947f853a25SElizabeth Figura 	EXPECT_EQ(EOVERFLOW, errno);
1957f853a25SElizabeth Figura 	check_sem_state(sem, 0, 2);
1967f853a25SElizabeth Figura 
1977f853a25SElizabeth Figura 	count = 2;
1987f853a25SElizabeth Figura 	ret = release_sem(sem, &count);
1997f853a25SElizabeth Figura 	EXPECT_EQ(0, ret);
2007f853a25SElizabeth Figura 	EXPECT_EQ(0, count);
2017f853a25SElizabeth Figura 	check_sem_state(sem, 2, 2);
2027f853a25SElizabeth Figura 
2037f853a25SElizabeth Figura 	ret = wait_any(fd, 1, &sem, 123, &index);
2047f853a25SElizabeth Figura 	EXPECT_EQ(0, ret);
2057f853a25SElizabeth Figura 	ret = wait_any(fd, 1, &sem, 123, &index);
2067f853a25SElizabeth Figura 	EXPECT_EQ(0, ret);
2077f853a25SElizabeth Figura 
2087f853a25SElizabeth Figura 	count = 1;
2097f853a25SElizabeth Figura 	ret = release_sem(sem, &count);
2107f853a25SElizabeth Figura 	EXPECT_EQ(0, ret);
2117f853a25SElizabeth Figura 	EXPECT_EQ(0, count);
2127f853a25SElizabeth Figura 	check_sem_state(sem, 1, 2);
2137f853a25SElizabeth Figura 
2147f853a25SElizabeth Figura 	count = ~0u;
2157f853a25SElizabeth Figura 	ret = release_sem(sem, &count);
2167f853a25SElizabeth Figura 	EXPECT_EQ(-1, ret);
2177f853a25SElizabeth Figura 	EXPECT_EQ(EOVERFLOW, errno);
2187f853a25SElizabeth Figura 	check_sem_state(sem, 1, 2);
2197f853a25SElizabeth Figura 
2207f853a25SElizabeth Figura 	close(sem);
2217f853a25SElizabeth Figura 
2227f853a25SElizabeth Figura 	close(fd);
2237f853a25SElizabeth Figura }
2247f853a25SElizabeth Figura 
TEST(mutex_state)225ae071aefSElizabeth Figura TEST(mutex_state)
226ae071aefSElizabeth Figura {
227ae071aefSElizabeth Figura 	struct ntsync_mutex_args mutex_args;
228ae071aefSElizabeth Figura 	__u32 owner, count, index;
229ae071aefSElizabeth Figura 	struct timespec timeout;
230ae071aefSElizabeth Figura 	int fd, ret, mutex;
231ae071aefSElizabeth Figura 
232ae071aefSElizabeth Figura 	clock_gettime(CLOCK_MONOTONIC, &timeout);
233ae071aefSElizabeth Figura 
234ae071aefSElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
235ae071aefSElizabeth Figura 	ASSERT_LE(0, fd);
236ae071aefSElizabeth Figura 
237ae071aefSElizabeth Figura 	mutex_args.owner = 123;
238ae071aefSElizabeth Figura 	mutex_args.count = 0;
239ae071aefSElizabeth Figura 	mutex = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
240ae071aefSElizabeth Figura 	EXPECT_EQ(-1, mutex);
241ae071aefSElizabeth Figura 	EXPECT_EQ(EINVAL, errno);
242ae071aefSElizabeth Figura 
243ae071aefSElizabeth Figura 	mutex_args.owner = 0;
244ae071aefSElizabeth Figura 	mutex_args.count = 2;
245ae071aefSElizabeth Figura 	mutex = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
246ae071aefSElizabeth Figura 	EXPECT_EQ(-1, mutex);
247ae071aefSElizabeth Figura 	EXPECT_EQ(EINVAL, errno);
248ae071aefSElizabeth Figura 
249ae071aefSElizabeth Figura 	mutex_args.owner = 123;
250ae071aefSElizabeth Figura 	mutex_args.count = 2;
251ae071aefSElizabeth Figura 	mutex = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
252ae071aefSElizabeth Figura 	EXPECT_LE(0, mutex);
253ae071aefSElizabeth Figura 	check_mutex_state(mutex, 2, 123);
254ae071aefSElizabeth Figura 
255ae071aefSElizabeth Figura 	ret = unlock_mutex(mutex, 0, &count);
256ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
257ae071aefSElizabeth Figura 	EXPECT_EQ(EINVAL, errno);
258ae071aefSElizabeth Figura 
259ae071aefSElizabeth Figura 	ret = unlock_mutex(mutex, 456, &count);
260ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
261ae071aefSElizabeth Figura 	EXPECT_EQ(EPERM, errno);
262ae071aefSElizabeth Figura 	check_mutex_state(mutex, 2, 123);
263ae071aefSElizabeth Figura 
264ae071aefSElizabeth Figura 	ret = unlock_mutex(mutex, 123, &count);
265ae071aefSElizabeth Figura 	EXPECT_EQ(0, ret);
266ae071aefSElizabeth Figura 	EXPECT_EQ(2, count);
267ae071aefSElizabeth Figura 	check_mutex_state(mutex, 1, 123);
268ae071aefSElizabeth Figura 
269ae071aefSElizabeth Figura 	ret = unlock_mutex(mutex, 123, &count);
270ae071aefSElizabeth Figura 	EXPECT_EQ(0, ret);
271ae071aefSElizabeth Figura 	EXPECT_EQ(1, count);
272ae071aefSElizabeth Figura 	check_mutex_state(mutex, 0, 0);
273ae071aefSElizabeth Figura 
274ae071aefSElizabeth Figura 	ret = unlock_mutex(mutex, 123, &count);
275ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
276ae071aefSElizabeth Figura 	EXPECT_EQ(EPERM, errno);
277ae071aefSElizabeth Figura 
278ae071aefSElizabeth Figura 	ret = wait_any(fd, 1, &mutex, 456, &index);
279ae071aefSElizabeth Figura 	EXPECT_EQ(0, ret);
280ae071aefSElizabeth Figura 	EXPECT_EQ(0, index);
281ae071aefSElizabeth Figura 	check_mutex_state(mutex, 1, 456);
282ae071aefSElizabeth Figura 
283ae071aefSElizabeth Figura 	ret = wait_any(fd, 1, &mutex, 456, &index);
284ae071aefSElizabeth Figura 	EXPECT_EQ(0, ret);
285ae071aefSElizabeth Figura 	EXPECT_EQ(0, index);
286ae071aefSElizabeth Figura 	check_mutex_state(mutex, 2, 456);
287ae071aefSElizabeth Figura 
288ae071aefSElizabeth Figura 	ret = unlock_mutex(mutex, 456, &count);
289ae071aefSElizabeth Figura 	EXPECT_EQ(0, ret);
290ae071aefSElizabeth Figura 	EXPECT_EQ(2, count);
291ae071aefSElizabeth Figura 	check_mutex_state(mutex, 1, 456);
292ae071aefSElizabeth Figura 
293ae071aefSElizabeth Figura 	ret = wait_any(fd, 1, &mutex, 123, &index);
294ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
295ae071aefSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
296ae071aefSElizabeth Figura 
297ae071aefSElizabeth Figura 	owner = 0;
298ae071aefSElizabeth Figura 	ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner);
299ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
300ae071aefSElizabeth Figura 	EXPECT_EQ(EINVAL, errno);
301ae071aefSElizabeth Figura 
302ae071aefSElizabeth Figura 	owner = 123;
303ae071aefSElizabeth Figura 	ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner);
304ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
305ae071aefSElizabeth Figura 	EXPECT_EQ(EPERM, errno);
306ae071aefSElizabeth Figura 	check_mutex_state(mutex, 1, 456);
307ae071aefSElizabeth Figura 
308ae071aefSElizabeth Figura 	owner = 456;
309ae071aefSElizabeth Figura 	ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner);
310ae071aefSElizabeth Figura 	EXPECT_EQ(0, ret);
311ae071aefSElizabeth Figura 
312ae071aefSElizabeth Figura 	memset(&mutex_args, 0xcc, sizeof(mutex_args));
313ae071aefSElizabeth Figura 	ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args);
314ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
315ae071aefSElizabeth Figura 	EXPECT_EQ(EOWNERDEAD, errno);
316ae071aefSElizabeth Figura 	EXPECT_EQ(0, mutex_args.count);
317ae071aefSElizabeth Figura 	EXPECT_EQ(0, mutex_args.owner);
318ae071aefSElizabeth Figura 
319ae071aefSElizabeth Figura 	memset(&mutex_args, 0xcc, sizeof(mutex_args));
320ae071aefSElizabeth Figura 	ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args);
321ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
322ae071aefSElizabeth Figura 	EXPECT_EQ(EOWNERDEAD, errno);
323ae071aefSElizabeth Figura 	EXPECT_EQ(0, mutex_args.count);
324ae071aefSElizabeth Figura 	EXPECT_EQ(0, mutex_args.owner);
325ae071aefSElizabeth Figura 
326ae071aefSElizabeth Figura 	ret = wait_any(fd, 1, &mutex, 123, &index);
327ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
328ae071aefSElizabeth Figura 	EXPECT_EQ(EOWNERDEAD, errno);
329ae071aefSElizabeth Figura 	EXPECT_EQ(0, index);
330ae071aefSElizabeth Figura 	check_mutex_state(mutex, 1, 123);
331ae071aefSElizabeth Figura 
332ae071aefSElizabeth Figura 	owner = 123;
333ae071aefSElizabeth Figura 	ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner);
334ae071aefSElizabeth Figura 	EXPECT_EQ(0, ret);
335ae071aefSElizabeth Figura 
336ae071aefSElizabeth Figura 	memset(&mutex_args, 0xcc, sizeof(mutex_args));
337ae071aefSElizabeth Figura 	ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args);
338ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
339ae071aefSElizabeth Figura 	EXPECT_EQ(EOWNERDEAD, errno);
340ae071aefSElizabeth Figura 	EXPECT_EQ(0, mutex_args.count);
341ae071aefSElizabeth Figura 	EXPECT_EQ(0, mutex_args.owner);
342ae071aefSElizabeth Figura 
343ae071aefSElizabeth Figura 	ret = wait_any(fd, 1, &mutex, 123, &index);
344ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
345ae071aefSElizabeth Figura 	EXPECT_EQ(EOWNERDEAD, errno);
346ae071aefSElizabeth Figura 	EXPECT_EQ(0, index);
347ae071aefSElizabeth Figura 	check_mutex_state(mutex, 1, 123);
348ae071aefSElizabeth Figura 
349ae071aefSElizabeth Figura 	close(mutex);
350ae071aefSElizabeth Figura 
351ae071aefSElizabeth Figura 	mutex_args.owner = 0;
352ae071aefSElizabeth Figura 	mutex_args.count = 0;
353ae071aefSElizabeth Figura 	mutex = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
354ae071aefSElizabeth Figura 	EXPECT_LE(0, mutex);
355ae071aefSElizabeth Figura 	check_mutex_state(mutex, 0, 0);
356ae071aefSElizabeth Figura 
357ae071aefSElizabeth Figura 	ret = wait_any(fd, 1, &mutex, 123, &index);
358ae071aefSElizabeth Figura 	EXPECT_EQ(0, ret);
359ae071aefSElizabeth Figura 	EXPECT_EQ(0, index);
360ae071aefSElizabeth Figura 	check_mutex_state(mutex, 1, 123);
361ae071aefSElizabeth Figura 
362ae071aefSElizabeth Figura 	close(mutex);
363ae071aefSElizabeth Figura 
364ae071aefSElizabeth Figura 	mutex_args.owner = 123;
365ae071aefSElizabeth Figura 	mutex_args.count = ~0u;
366ae071aefSElizabeth Figura 	mutex = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
367ae071aefSElizabeth Figura 	EXPECT_LE(0, mutex);
368ae071aefSElizabeth Figura 	check_mutex_state(mutex, ~0u, 123);
369ae071aefSElizabeth Figura 
370ae071aefSElizabeth Figura 	ret = wait_any(fd, 1, &mutex, 123, &index);
371ae071aefSElizabeth Figura 	EXPECT_EQ(-1, ret);
372ae071aefSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
373ae071aefSElizabeth Figura 
374ae071aefSElizabeth Figura 	close(mutex);
375ae071aefSElizabeth Figura 
376ae071aefSElizabeth Figura 	close(fd);
377ae071aefSElizabeth Figura }
378ae071aefSElizabeth Figura 
TEST(manual_event_state)379d2083b5fSElizabeth Figura TEST(manual_event_state)
380d2083b5fSElizabeth Figura {
381d2083b5fSElizabeth Figura 	struct ntsync_event_args event_args;
382d2083b5fSElizabeth Figura 	__u32 index, signaled;
383d2083b5fSElizabeth Figura 	int fd, event, ret;
384d2083b5fSElizabeth Figura 
385d2083b5fSElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
386d2083b5fSElizabeth Figura 	ASSERT_LE(0, fd);
387d2083b5fSElizabeth Figura 
388d2083b5fSElizabeth Figura 	event_args.manual = 1;
389d2083b5fSElizabeth Figura 	event_args.signaled = 0;
390d2083b5fSElizabeth Figura 	event = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args);
391d2083b5fSElizabeth Figura 	EXPECT_LE(0, event);
392d2083b5fSElizabeth Figura 	check_event_state(event, 0, 1);
393d2083b5fSElizabeth Figura 
394d2083b5fSElizabeth Figura 	signaled = 0xdeadbeef;
395d2083b5fSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled);
396d2083b5fSElizabeth Figura 	EXPECT_EQ(0, ret);
397d2083b5fSElizabeth Figura 	EXPECT_EQ(0, signaled);
398d2083b5fSElizabeth Figura 	check_event_state(event, 1, 1);
399d2083b5fSElizabeth Figura 
400d2083b5fSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled);
401d2083b5fSElizabeth Figura 	EXPECT_EQ(0, ret);
402d2083b5fSElizabeth Figura 	EXPECT_EQ(1, signaled);
403d2083b5fSElizabeth Figura 	check_event_state(event, 1, 1);
404d2083b5fSElizabeth Figura 
405d2083b5fSElizabeth Figura 	ret = wait_any(fd, 1, &event, 123, &index);
406d2083b5fSElizabeth Figura 	EXPECT_EQ(0, ret);
407d2083b5fSElizabeth Figura 	EXPECT_EQ(0, index);
408d2083b5fSElizabeth Figura 	check_event_state(event, 1, 1);
409d2083b5fSElizabeth Figura 
410d2083b5fSElizabeth Figura 	signaled = 0xdeadbeef;
411d2083b5fSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled);
412d2083b5fSElizabeth Figura 	EXPECT_EQ(0, ret);
413d2083b5fSElizabeth Figura 	EXPECT_EQ(1, signaled);
414d2083b5fSElizabeth Figura 	check_event_state(event, 0, 1);
415d2083b5fSElizabeth Figura 
416d2083b5fSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled);
417d2083b5fSElizabeth Figura 	EXPECT_EQ(0, ret);
418d2083b5fSElizabeth Figura 	EXPECT_EQ(0, signaled);
419d2083b5fSElizabeth Figura 	check_event_state(event, 0, 1);
420d2083b5fSElizabeth Figura 
421d2083b5fSElizabeth Figura 	ret = wait_any(fd, 1, &event, 123, &index);
422d2083b5fSElizabeth Figura 	EXPECT_EQ(-1, ret);
423d2083b5fSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
424d2083b5fSElizabeth Figura 
425d2083b5fSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled);
426d2083b5fSElizabeth Figura 	EXPECT_EQ(0, ret);
427d2083b5fSElizabeth Figura 	EXPECT_EQ(0, signaled);
428d2083b5fSElizabeth Figura 
429d2083b5fSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled);
430d2083b5fSElizabeth Figura 	EXPECT_EQ(0, ret);
431d2083b5fSElizabeth Figura 	EXPECT_EQ(1, signaled);
432d2083b5fSElizabeth Figura 	check_event_state(event, 0, 1);
433d2083b5fSElizabeth Figura 
434d2083b5fSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled);
435d2083b5fSElizabeth Figura 	EXPECT_EQ(0, ret);
436d2083b5fSElizabeth Figura 	EXPECT_EQ(0, signaled);
437d2083b5fSElizabeth Figura 	check_event_state(event, 0, 1);
438d2083b5fSElizabeth Figura 
439d2083b5fSElizabeth Figura 	close(event);
440d2083b5fSElizabeth Figura 
441d2083b5fSElizabeth Figura 	close(fd);
442d2083b5fSElizabeth Figura }
443d2083b5fSElizabeth Figura 
TEST(auto_event_state)444b4e4dd5dSElizabeth Figura TEST(auto_event_state)
445b4e4dd5dSElizabeth Figura {
446b4e4dd5dSElizabeth Figura 	struct ntsync_event_args event_args;
447b4e4dd5dSElizabeth Figura 	__u32 index, signaled;
448b4e4dd5dSElizabeth Figura 	int fd, event, ret;
449b4e4dd5dSElizabeth Figura 
450b4e4dd5dSElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
451b4e4dd5dSElizabeth Figura 	ASSERT_LE(0, fd);
452b4e4dd5dSElizabeth Figura 
453b4e4dd5dSElizabeth Figura 	event_args.manual = 0;
454b4e4dd5dSElizabeth Figura 	event_args.signaled = 1;
455b4e4dd5dSElizabeth Figura 	event = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args);
456b4e4dd5dSElizabeth Figura 	EXPECT_LE(0, event);
457b4e4dd5dSElizabeth Figura 
458b4e4dd5dSElizabeth Figura 	check_event_state(event, 1, 0);
459b4e4dd5dSElizabeth Figura 
460b4e4dd5dSElizabeth Figura 	signaled = 0xdeadbeef;
461b4e4dd5dSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled);
462b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, ret);
463b4e4dd5dSElizabeth Figura 	EXPECT_EQ(1, signaled);
464b4e4dd5dSElizabeth Figura 	check_event_state(event, 1, 0);
465b4e4dd5dSElizabeth Figura 
466b4e4dd5dSElizabeth Figura 	ret = wait_any(fd, 1, &event, 123, &index);
467b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, ret);
468b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, index);
469b4e4dd5dSElizabeth Figura 	check_event_state(event, 0, 0);
470b4e4dd5dSElizabeth Figura 
471b4e4dd5dSElizabeth Figura 	signaled = 0xdeadbeef;
472b4e4dd5dSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled);
473b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, ret);
474b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, signaled);
475b4e4dd5dSElizabeth Figura 	check_event_state(event, 0, 0);
476b4e4dd5dSElizabeth Figura 
477b4e4dd5dSElizabeth Figura 	ret = wait_any(fd, 1, &event, 123, &index);
478b4e4dd5dSElizabeth Figura 	EXPECT_EQ(-1, ret);
479b4e4dd5dSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
480b4e4dd5dSElizabeth Figura 
481b4e4dd5dSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled);
482b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, ret);
483b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, signaled);
484b4e4dd5dSElizabeth Figura 
485b4e4dd5dSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled);
486b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, ret);
487b4e4dd5dSElizabeth Figura 	EXPECT_EQ(1, signaled);
488b4e4dd5dSElizabeth Figura 	check_event_state(event, 0, 0);
489b4e4dd5dSElizabeth Figura 
490b4e4dd5dSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_PULSE, &signaled);
491b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, ret);
492b4e4dd5dSElizabeth Figura 	EXPECT_EQ(0, signaled);
493b4e4dd5dSElizabeth Figura 	check_event_state(event, 0, 0);
494b4e4dd5dSElizabeth Figura 
495b4e4dd5dSElizabeth Figura 	close(event);
496b4e4dd5dSElizabeth Figura 
497b4e4dd5dSElizabeth Figura 	close(fd);
498b4e4dd5dSElizabeth Figura }
499b4e4dd5dSElizabeth Figura 
TEST(test_wait_any)50044554569SElizabeth Figura TEST(test_wait_any)
50144554569SElizabeth Figura {
50244554569SElizabeth Figura 	int objs[NTSYNC_MAX_WAIT_COUNT + 1], fd, ret;
50344554569SElizabeth Figura 	struct ntsync_mutex_args mutex_args = {0};
50444554569SElizabeth Figura 	struct ntsync_sem_args sem_args = {0};
50544554569SElizabeth Figura 	__u32 owner, index, count, i;
50644554569SElizabeth Figura 	struct timespec timeout;
50744554569SElizabeth Figura 
50844554569SElizabeth Figura 	clock_gettime(CLOCK_MONOTONIC, &timeout);
50944554569SElizabeth Figura 
51044554569SElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
51144554569SElizabeth Figura 	ASSERT_LE(0, fd);
51244554569SElizabeth Figura 
51344554569SElizabeth Figura 	sem_args.count = 2;
51444554569SElizabeth Figura 	sem_args.max = 3;
51544554569SElizabeth Figura 	objs[0] = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
51644554569SElizabeth Figura 	EXPECT_LE(0, objs[0]);
51744554569SElizabeth Figura 
51844554569SElizabeth Figura 	mutex_args.owner = 0;
51944554569SElizabeth Figura 	mutex_args.count = 0;
52044554569SElizabeth Figura 	objs[1] = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
52144554569SElizabeth Figura 	EXPECT_LE(0, objs[1]);
52244554569SElizabeth Figura 
52344554569SElizabeth Figura 	ret = wait_any(fd, 2, objs, 123, &index);
52444554569SElizabeth Figura 	EXPECT_EQ(0, ret);
52544554569SElizabeth Figura 	EXPECT_EQ(0, index);
52644554569SElizabeth Figura 	check_sem_state(objs[0], 1, 3);
52744554569SElizabeth Figura 	check_mutex_state(objs[1], 0, 0);
52844554569SElizabeth Figura 
52944554569SElizabeth Figura 	ret = wait_any(fd, 2, objs, 123, &index);
53044554569SElizabeth Figura 	EXPECT_EQ(0, ret);
53144554569SElizabeth Figura 	EXPECT_EQ(0, index);
53244554569SElizabeth Figura 	check_sem_state(objs[0], 0, 3);
53344554569SElizabeth Figura 	check_mutex_state(objs[1], 0, 0);
53444554569SElizabeth Figura 
53544554569SElizabeth Figura 	ret = wait_any(fd, 2, objs, 123, &index);
53644554569SElizabeth Figura 	EXPECT_EQ(0, ret);
53744554569SElizabeth Figura 	EXPECT_EQ(1, index);
53844554569SElizabeth Figura 	check_sem_state(objs[0], 0, 3);
53944554569SElizabeth Figura 	check_mutex_state(objs[1], 1, 123);
54044554569SElizabeth Figura 
54144554569SElizabeth Figura 	count = 1;
54244554569SElizabeth Figura 	ret = release_sem(objs[0], &count);
54344554569SElizabeth Figura 	EXPECT_EQ(0, ret);
54444554569SElizabeth Figura 	EXPECT_EQ(0, count);
54544554569SElizabeth Figura 
54644554569SElizabeth Figura 	ret = wait_any(fd, 2, objs, 123, &index);
54744554569SElizabeth Figura 	EXPECT_EQ(0, ret);
54844554569SElizabeth Figura 	EXPECT_EQ(0, index);
54944554569SElizabeth Figura 	check_sem_state(objs[0], 0, 3);
55044554569SElizabeth Figura 	check_mutex_state(objs[1], 1, 123);
55144554569SElizabeth Figura 
55244554569SElizabeth Figura 	ret = wait_any(fd, 2, objs, 123, &index);
55344554569SElizabeth Figura 	EXPECT_EQ(0, ret);
55444554569SElizabeth Figura 	EXPECT_EQ(1, index);
55544554569SElizabeth Figura 	check_sem_state(objs[0], 0, 3);
55644554569SElizabeth Figura 	check_mutex_state(objs[1], 2, 123);
55744554569SElizabeth Figura 
55844554569SElizabeth Figura 	ret = wait_any(fd, 2, objs, 456, &index);
55944554569SElizabeth Figura 	EXPECT_EQ(-1, ret);
56044554569SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
56144554569SElizabeth Figura 
56244554569SElizabeth Figura 	owner = 123;
56344554569SElizabeth Figura 	ret = ioctl(objs[1], NTSYNC_IOC_MUTEX_KILL, &owner);
56444554569SElizabeth Figura 	EXPECT_EQ(0, ret);
56544554569SElizabeth Figura 
56644554569SElizabeth Figura 	ret = wait_any(fd, 2, objs, 456, &index);
56744554569SElizabeth Figura 	EXPECT_EQ(-1, ret);
56844554569SElizabeth Figura 	EXPECT_EQ(EOWNERDEAD, errno);
56944554569SElizabeth Figura 	EXPECT_EQ(1, index);
57044554569SElizabeth Figura 
57144554569SElizabeth Figura 	ret = wait_any(fd, 2, objs, 456, &index);
57244554569SElizabeth Figura 	EXPECT_EQ(0, ret);
57344554569SElizabeth Figura 	EXPECT_EQ(1, index);
57444554569SElizabeth Figura 
57544554569SElizabeth Figura 	close(objs[1]);
57644554569SElizabeth Figura 
57744554569SElizabeth Figura 	/* test waiting on the same object twice */
57844554569SElizabeth Figura 
57944554569SElizabeth Figura 	count = 2;
58044554569SElizabeth Figura 	ret = release_sem(objs[0], &count);
58144554569SElizabeth Figura 	EXPECT_EQ(0, ret);
58244554569SElizabeth Figura 	EXPECT_EQ(0, count);
58344554569SElizabeth Figura 
58444554569SElizabeth Figura 	objs[1] = objs[0];
58544554569SElizabeth Figura 	ret = wait_any(fd, 2, objs, 456, &index);
58644554569SElizabeth Figura 	EXPECT_EQ(0, ret);
58744554569SElizabeth Figura 	EXPECT_EQ(0, index);
58844554569SElizabeth Figura 	check_sem_state(objs[0], 1, 3);
58944554569SElizabeth Figura 
59044554569SElizabeth Figura 	ret = wait_any(fd, 0, NULL, 456, &index);
59144554569SElizabeth Figura 	EXPECT_EQ(-1, ret);
59244554569SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
59344554569SElizabeth Figura 
59444554569SElizabeth Figura 	for (i = 1; i < NTSYNC_MAX_WAIT_COUNT + 1; ++i)
59544554569SElizabeth Figura 		objs[i] = objs[0];
59644554569SElizabeth Figura 
59744554569SElizabeth Figura 	ret = wait_any(fd, NTSYNC_MAX_WAIT_COUNT, objs, 123, &index);
59844554569SElizabeth Figura 	EXPECT_EQ(0, ret);
59944554569SElizabeth Figura 	EXPECT_EQ(0, index);
60044554569SElizabeth Figura 
60144554569SElizabeth Figura 	ret = wait_any(fd, NTSYNC_MAX_WAIT_COUNT + 1, objs, 123, &index);
60244554569SElizabeth Figura 	EXPECT_EQ(-1, ret);
60344554569SElizabeth Figura 	EXPECT_EQ(EINVAL, errno);
60444554569SElizabeth Figura 
60544554569SElizabeth Figura 	ret = wait_any(fd, -1, objs, 123, &index);
60644554569SElizabeth Figura 	EXPECT_EQ(-1, ret);
60744554569SElizabeth Figura 	EXPECT_EQ(EINVAL, errno);
60844554569SElizabeth Figura 
60944554569SElizabeth Figura 	close(objs[0]);
61044554569SElizabeth Figura 
61144554569SElizabeth Figura 	close(fd);
61244554569SElizabeth Figura }
61344554569SElizabeth Figura 
TEST(test_wait_all)614d168f689SElizabeth Figura TEST(test_wait_all)
615d168f689SElizabeth Figura {
616a2e5a8ceSElizabeth Figura 	struct ntsync_event_args event_args = {0};
617d168f689SElizabeth Figura 	struct ntsync_mutex_args mutex_args = {0};
618d168f689SElizabeth Figura 	struct ntsync_sem_args sem_args = {0};
619d168f689SElizabeth Figura 	__u32 owner, index, count;
620d168f689SElizabeth Figura 	int objs[2], fd, ret;
621d168f689SElizabeth Figura 
622d168f689SElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
623d168f689SElizabeth Figura 	ASSERT_LE(0, fd);
624d168f689SElizabeth Figura 
625d168f689SElizabeth Figura 	sem_args.count = 2;
626d168f689SElizabeth Figura 	sem_args.max = 3;
627d168f689SElizabeth Figura 	objs[0] = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
628d168f689SElizabeth Figura 	EXPECT_LE(0, objs[0]);
629d168f689SElizabeth Figura 
630d168f689SElizabeth Figura 	mutex_args.owner = 0;
631d168f689SElizabeth Figura 	mutex_args.count = 0;
632d168f689SElizabeth Figura 	objs[1] = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
633d168f689SElizabeth Figura 	EXPECT_LE(0, objs[1]);
634d168f689SElizabeth Figura 
635d168f689SElizabeth Figura 	ret = wait_all(fd, 2, objs, 123, &index);
636d168f689SElizabeth Figura 	EXPECT_EQ(0, ret);
637d168f689SElizabeth Figura 	EXPECT_EQ(0, index);
638d168f689SElizabeth Figura 	check_sem_state(objs[0], 1, 3);
639d168f689SElizabeth Figura 	check_mutex_state(objs[1], 1, 123);
640d168f689SElizabeth Figura 
641d168f689SElizabeth Figura 	ret = wait_all(fd, 2, objs, 456, &index);
642d168f689SElizabeth Figura 	EXPECT_EQ(-1, ret);
643d168f689SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
644d168f689SElizabeth Figura 	check_sem_state(objs[0], 1, 3);
645d168f689SElizabeth Figura 	check_mutex_state(objs[1], 1, 123);
646d168f689SElizabeth Figura 
647d168f689SElizabeth Figura 	ret = wait_all(fd, 2, objs, 123, &index);
648d168f689SElizabeth Figura 	EXPECT_EQ(0, ret);
649d168f689SElizabeth Figura 	EXPECT_EQ(0, index);
650d168f689SElizabeth Figura 	check_sem_state(objs[0], 0, 3);
651d168f689SElizabeth Figura 	check_mutex_state(objs[1], 2, 123);
652d168f689SElizabeth Figura 
653d168f689SElizabeth Figura 	ret = wait_all(fd, 2, objs, 123, &index);
654d168f689SElizabeth Figura 	EXPECT_EQ(-1, ret);
655d168f689SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
656d168f689SElizabeth Figura 	check_sem_state(objs[0], 0, 3);
657d168f689SElizabeth Figura 	check_mutex_state(objs[1], 2, 123);
658d168f689SElizabeth Figura 
659d168f689SElizabeth Figura 	count = 3;
660d168f689SElizabeth Figura 	ret = release_sem(objs[0], &count);
661d168f689SElizabeth Figura 	EXPECT_EQ(0, ret);
662d168f689SElizabeth Figura 	EXPECT_EQ(0, count);
663d168f689SElizabeth Figura 
664d168f689SElizabeth Figura 	ret = wait_all(fd, 2, objs, 123, &index);
665d168f689SElizabeth Figura 	EXPECT_EQ(0, ret);
666d168f689SElizabeth Figura 	EXPECT_EQ(0, index);
667d168f689SElizabeth Figura 	check_sem_state(objs[0], 2, 3);
668d168f689SElizabeth Figura 	check_mutex_state(objs[1], 3, 123);
669d168f689SElizabeth Figura 
670d168f689SElizabeth Figura 	owner = 123;
671d168f689SElizabeth Figura 	ret = ioctl(objs[1], NTSYNC_IOC_MUTEX_KILL, &owner);
672d168f689SElizabeth Figura 	EXPECT_EQ(0, ret);
673d168f689SElizabeth Figura 
674d168f689SElizabeth Figura 	ret = wait_all(fd, 2, objs, 123, &index);
675d168f689SElizabeth Figura 	EXPECT_EQ(-1, ret);
676d168f689SElizabeth Figura 	EXPECT_EQ(EOWNERDEAD, errno);
677d168f689SElizabeth Figura 	check_sem_state(objs[0], 1, 3);
678d168f689SElizabeth Figura 	check_mutex_state(objs[1], 1, 123);
679d168f689SElizabeth Figura 
680d168f689SElizabeth Figura 	close(objs[1]);
681d168f689SElizabeth Figura 
682a2e5a8ceSElizabeth Figura 	event_args.manual = true;
683a2e5a8ceSElizabeth Figura 	event_args.signaled = true;
684a2e5a8ceSElizabeth Figura 	objs[1] = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args);
685a2e5a8ceSElizabeth Figura 	EXPECT_LE(0, objs[1]);
686a2e5a8ceSElizabeth Figura 
687a2e5a8ceSElizabeth Figura 	ret = wait_all(fd, 2, objs, 123, &index);
688a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
689a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, index);
690a2e5a8ceSElizabeth Figura 	check_sem_state(objs[0], 0, 3);
691a2e5a8ceSElizabeth Figura 	check_event_state(objs[1], 1, 1);
692a2e5a8ceSElizabeth Figura 
693a2e5a8ceSElizabeth Figura 	close(objs[1]);
694a2e5a8ceSElizabeth Figura 
695d168f689SElizabeth Figura 	/* test waiting on the same object twice */
696d168f689SElizabeth Figura 	objs[1] = objs[0];
697d168f689SElizabeth Figura 	ret = wait_all(fd, 2, objs, 123, &index);
698d168f689SElizabeth Figura 	EXPECT_EQ(-1, ret);
699d168f689SElizabeth Figura 	EXPECT_EQ(EINVAL, errno);
700d168f689SElizabeth Figura 
701d168f689SElizabeth Figura 	close(objs[0]);
702d168f689SElizabeth Figura 
703d168f689SElizabeth Figura 	close(fd);
704d168f689SElizabeth Figura }
705d168f689SElizabeth Figura 
706f2327985SElizabeth Figura struct wake_args {
707f2327985SElizabeth Figura 	int fd;
708f2327985SElizabeth Figura 	int obj;
709f2327985SElizabeth Figura };
710f2327985SElizabeth Figura 
711f2327985SElizabeth Figura struct wait_args {
712f2327985SElizabeth Figura 	int fd;
713f2327985SElizabeth Figura 	unsigned long request;
714f2327985SElizabeth Figura 	struct ntsync_wait_args *args;
715f2327985SElizabeth Figura 	int ret;
716f2327985SElizabeth Figura 	int err;
717f2327985SElizabeth Figura };
718f2327985SElizabeth Figura 
wait_thread(void * arg)719f2327985SElizabeth Figura static void *wait_thread(void *arg)
720f2327985SElizabeth Figura {
721f2327985SElizabeth Figura 	struct wait_args *args = arg;
722f2327985SElizabeth Figura 
723f2327985SElizabeth Figura 	args->ret = ioctl(args->fd, args->request, args->args);
724f2327985SElizabeth Figura 	args->err = errno;
725f2327985SElizabeth Figura 	return NULL;
726f2327985SElizabeth Figura }
727f2327985SElizabeth Figura 
get_abs_timeout(unsigned int ms)728f2327985SElizabeth Figura static __u64 get_abs_timeout(unsigned int ms)
729f2327985SElizabeth Figura {
730f2327985SElizabeth Figura 	struct timespec timeout;
731f2327985SElizabeth Figura 	clock_gettime(CLOCK_MONOTONIC, &timeout);
732f2327985SElizabeth Figura 	return (timeout.tv_sec * 1000000000) + timeout.tv_nsec + (ms * 1000000);
733f2327985SElizabeth Figura }
734f2327985SElizabeth Figura 
wait_for_thread(pthread_t thread,unsigned int ms)735f2327985SElizabeth Figura static int wait_for_thread(pthread_t thread, unsigned int ms)
736f2327985SElizabeth Figura {
737f2327985SElizabeth Figura 	struct timespec timeout;
738f2327985SElizabeth Figura 
739f2327985SElizabeth Figura 	clock_gettime(CLOCK_REALTIME, &timeout);
740f2327985SElizabeth Figura 	timeout.tv_nsec += ms * 1000000;
741f2327985SElizabeth Figura 	timeout.tv_sec += (timeout.tv_nsec / 1000000000);
742f2327985SElizabeth Figura 	timeout.tv_nsec %= 1000000000;
743f2327985SElizabeth Figura 	return pthread_timedjoin_np(thread, NULL, &timeout);
744f2327985SElizabeth Figura }
745f2327985SElizabeth Figura 
TEST(wake_any)746f2327985SElizabeth Figura TEST(wake_any)
747f2327985SElizabeth Figura {
748a2e5a8ceSElizabeth Figura 	struct ntsync_event_args event_args = {0};
749f2327985SElizabeth Figura 	struct ntsync_mutex_args mutex_args = {0};
750f2327985SElizabeth Figura 	struct ntsync_wait_args wait_args = {0};
751f2327985SElizabeth Figura 	struct ntsync_sem_args sem_args = {0};
752f2327985SElizabeth Figura 	struct wait_args thread_args;
753a2e5a8ceSElizabeth Figura 	__u32 count, index, signaled;
754f2327985SElizabeth Figura 	int objs[2], fd, ret;
755f2327985SElizabeth Figura 	pthread_t thread;
756f2327985SElizabeth Figura 
757f2327985SElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
758f2327985SElizabeth Figura 	ASSERT_LE(0, fd);
759f2327985SElizabeth Figura 
760f2327985SElizabeth Figura 	sem_args.count = 0;
761f2327985SElizabeth Figura 	sem_args.max = 3;
762f2327985SElizabeth Figura 	objs[0] = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
763f2327985SElizabeth Figura 	EXPECT_LE(0, objs[0]);
764f2327985SElizabeth Figura 
765f2327985SElizabeth Figura 	mutex_args.owner = 123;
766f2327985SElizabeth Figura 	mutex_args.count = 1;
767f2327985SElizabeth Figura 	objs[1] = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
768f2327985SElizabeth Figura 	EXPECT_LE(0, objs[1]);
769f2327985SElizabeth Figura 
770f2327985SElizabeth Figura 	/* test waking the semaphore */
771f2327985SElizabeth Figura 
772f2327985SElizabeth Figura 	wait_args.timeout = get_abs_timeout(1000);
773f2327985SElizabeth Figura 	wait_args.objs = (uintptr_t)objs;
774f2327985SElizabeth Figura 	wait_args.count = 2;
775f2327985SElizabeth Figura 	wait_args.owner = 456;
776f2327985SElizabeth Figura 	wait_args.index = 0xdeadbeef;
777f2327985SElizabeth Figura 	thread_args.fd = fd;
778f2327985SElizabeth Figura 	thread_args.args = &wait_args;
779f2327985SElizabeth Figura 	thread_args.request = NTSYNC_IOC_WAIT_ANY;
780f2327985SElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
781f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
782f2327985SElizabeth Figura 
783f2327985SElizabeth Figura 	ret = wait_for_thread(thread, 100);
784f2327985SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
785f2327985SElizabeth Figura 
786f2327985SElizabeth Figura 	count = 1;
787f2327985SElizabeth Figura 	ret = release_sem(objs[0], &count);
788f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
789f2327985SElizabeth Figura 	EXPECT_EQ(0, count);
790f2327985SElizabeth Figura 	check_sem_state(objs[0], 0, 3);
791f2327985SElizabeth Figura 
792f2327985SElizabeth Figura 	ret = wait_for_thread(thread, 100);
793f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
794f2327985SElizabeth Figura 	EXPECT_EQ(0, thread_args.ret);
795f2327985SElizabeth Figura 	EXPECT_EQ(0, wait_args.index);
796f2327985SElizabeth Figura 
797f2327985SElizabeth Figura 	/* test waking the mutex */
798f2327985SElizabeth Figura 
799f2327985SElizabeth Figura 	/* first grab it again for owner 123 */
800f2327985SElizabeth Figura 	ret = wait_any(fd, 1, &objs[1], 123, &index);
801f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
802f2327985SElizabeth Figura 	EXPECT_EQ(0, index);
803f2327985SElizabeth Figura 
804f2327985SElizabeth Figura 	wait_args.timeout = get_abs_timeout(1000);
805f2327985SElizabeth Figura 	wait_args.owner = 456;
806f2327985SElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
807f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
808f2327985SElizabeth Figura 
809f2327985SElizabeth Figura 	ret = wait_for_thread(thread, 100);
810f2327985SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
811f2327985SElizabeth Figura 
812f2327985SElizabeth Figura 	ret = unlock_mutex(objs[1], 123, &count);
813f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
814f2327985SElizabeth Figura 	EXPECT_EQ(2, count);
815f2327985SElizabeth Figura 
816f2327985SElizabeth Figura 	ret = pthread_tryjoin_np(thread, NULL);
817f2327985SElizabeth Figura 	EXPECT_EQ(EBUSY, ret);
818f2327985SElizabeth Figura 
819f2327985SElizabeth Figura 	ret = unlock_mutex(objs[1], 123, &count);
820f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
821f2327985SElizabeth Figura 	EXPECT_EQ(1, mutex_args.count);
822f2327985SElizabeth Figura 	check_mutex_state(objs[1], 1, 456);
823f2327985SElizabeth Figura 
824f2327985SElizabeth Figura 	ret = wait_for_thread(thread, 100);
825f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
826f2327985SElizabeth Figura 	EXPECT_EQ(0, thread_args.ret);
827f2327985SElizabeth Figura 	EXPECT_EQ(1, wait_args.index);
828f2327985SElizabeth Figura 
829a2e5a8ceSElizabeth Figura 	close(objs[1]);
830a2e5a8ceSElizabeth Figura 
831a2e5a8ceSElizabeth Figura 	/* test waking events */
832a2e5a8ceSElizabeth Figura 
833a2e5a8ceSElizabeth Figura 	event_args.manual = false;
834a2e5a8ceSElizabeth Figura 	event_args.signaled = false;
835a2e5a8ceSElizabeth Figura 	objs[1] = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args);
836a2e5a8ceSElizabeth Figura 	EXPECT_LE(0, objs[1]);
837a2e5a8ceSElizabeth Figura 
838a2e5a8ceSElizabeth Figura 	wait_args.timeout = get_abs_timeout(1000);
839a2e5a8ceSElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
840a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
841a2e5a8ceSElizabeth Figura 
842a2e5a8ceSElizabeth Figura 	ret = wait_for_thread(thread, 100);
843a2e5a8ceSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
844a2e5a8ceSElizabeth Figura 
845a2e5a8ceSElizabeth Figura 	ret = ioctl(objs[1], NTSYNC_IOC_EVENT_SET, &signaled);
846a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
847a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, signaled);
848a2e5a8ceSElizabeth Figura 	check_event_state(objs[1], 0, 0);
849a2e5a8ceSElizabeth Figura 
850a2e5a8ceSElizabeth Figura 	ret = wait_for_thread(thread, 100);
851a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
852a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, thread_args.ret);
853a2e5a8ceSElizabeth Figura 	EXPECT_EQ(1, wait_args.index);
854a2e5a8ceSElizabeth Figura 
855a2e5a8ceSElizabeth Figura 	wait_args.timeout = get_abs_timeout(1000);
856a2e5a8ceSElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
857a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
858a2e5a8ceSElizabeth Figura 
859a2e5a8ceSElizabeth Figura 	ret = wait_for_thread(thread, 100);
860a2e5a8ceSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
861a2e5a8ceSElizabeth Figura 
862a2e5a8ceSElizabeth Figura 	ret = ioctl(objs[1], NTSYNC_IOC_EVENT_PULSE, &signaled);
863a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
864a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, signaled);
865a2e5a8ceSElizabeth Figura 	check_event_state(objs[1], 0, 0);
866a2e5a8ceSElizabeth Figura 
867a2e5a8ceSElizabeth Figura 	ret = wait_for_thread(thread, 100);
868a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
869a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, thread_args.ret);
870a2e5a8ceSElizabeth Figura 	EXPECT_EQ(1, wait_args.index);
871a2e5a8ceSElizabeth Figura 
872a2e5a8ceSElizabeth Figura 	close(objs[1]);
873a2e5a8ceSElizabeth Figura 
874a2e5a8ceSElizabeth Figura 	event_args.manual = true;
875a2e5a8ceSElizabeth Figura 	event_args.signaled = false;
876a2e5a8ceSElizabeth Figura 	objs[1] = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args);
877a2e5a8ceSElizabeth Figura 	EXPECT_LE(0, objs[1]);
878a2e5a8ceSElizabeth Figura 
879a2e5a8ceSElizabeth Figura 	wait_args.timeout = get_abs_timeout(1000);
880a2e5a8ceSElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
881a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
882a2e5a8ceSElizabeth Figura 
883a2e5a8ceSElizabeth Figura 	ret = wait_for_thread(thread, 100);
884a2e5a8ceSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
885a2e5a8ceSElizabeth Figura 
886a2e5a8ceSElizabeth Figura 	ret = ioctl(objs[1], NTSYNC_IOC_EVENT_SET, &signaled);
887a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
888a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, signaled);
889a2e5a8ceSElizabeth Figura 	check_event_state(objs[1], 1, 1);
890a2e5a8ceSElizabeth Figura 
891a2e5a8ceSElizabeth Figura 	ret = wait_for_thread(thread, 100);
892a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
893a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, thread_args.ret);
894a2e5a8ceSElizabeth Figura 	EXPECT_EQ(1, wait_args.index);
895a2e5a8ceSElizabeth Figura 
896a2e5a8ceSElizabeth Figura 	ret = ioctl(objs[1], NTSYNC_IOC_EVENT_RESET, &signaled);
897a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
898a2e5a8ceSElizabeth Figura 	EXPECT_EQ(1, signaled);
899a2e5a8ceSElizabeth Figura 
900a2e5a8ceSElizabeth Figura 	wait_args.timeout = get_abs_timeout(1000);
901a2e5a8ceSElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
902a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
903a2e5a8ceSElizabeth Figura 
904a2e5a8ceSElizabeth Figura 	ret = wait_for_thread(thread, 100);
905a2e5a8ceSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
906a2e5a8ceSElizabeth Figura 
907a2e5a8ceSElizabeth Figura 	ret = ioctl(objs[1], NTSYNC_IOC_EVENT_PULSE, &signaled);
908a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
909a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, signaled);
910a2e5a8ceSElizabeth Figura 	check_event_state(objs[1], 0, 1);
911a2e5a8ceSElizabeth Figura 
912a2e5a8ceSElizabeth Figura 	ret = wait_for_thread(thread, 100);
913a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
914a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, thread_args.ret);
915a2e5a8ceSElizabeth Figura 	EXPECT_EQ(1, wait_args.index);
916a2e5a8ceSElizabeth Figura 
917f2327985SElizabeth Figura 	/* delete an object while it's being waited on */
918f2327985SElizabeth Figura 
919f2327985SElizabeth Figura 	wait_args.timeout = get_abs_timeout(200);
920f2327985SElizabeth Figura 	wait_args.owner = 123;
921f2327985SElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
922f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
923f2327985SElizabeth Figura 
924f2327985SElizabeth Figura 	ret = wait_for_thread(thread, 100);
925f2327985SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
926f2327985SElizabeth Figura 
927f2327985SElizabeth Figura 	close(objs[0]);
928f2327985SElizabeth Figura 	close(objs[1]);
929f2327985SElizabeth Figura 
930f2327985SElizabeth Figura 	ret = wait_for_thread(thread, 200);
931f2327985SElizabeth Figura 	EXPECT_EQ(0, ret);
932f2327985SElizabeth Figura 	EXPECT_EQ(-1, thread_args.ret);
933f2327985SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, thread_args.err);
934f2327985SElizabeth Figura 
935f2327985SElizabeth Figura 	close(fd);
936f2327985SElizabeth Figura }
937f2327985SElizabeth Figura 
TEST(wake_all)93872a651c1SElizabeth Figura TEST(wake_all)
93972a651c1SElizabeth Figura {
940a2e5a8ceSElizabeth Figura 	struct ntsync_event_args manual_event_args = {0};
941a2e5a8ceSElizabeth Figura 	struct ntsync_event_args auto_event_args = {0};
94272a651c1SElizabeth Figura 	struct ntsync_mutex_args mutex_args = {0};
94372a651c1SElizabeth Figura 	struct ntsync_wait_args wait_args = {0};
94472a651c1SElizabeth Figura 	struct ntsync_sem_args sem_args = {0};
94572a651c1SElizabeth Figura 	struct wait_args thread_args;
946a2e5a8ceSElizabeth Figura 	__u32 count, index, signaled;
947a2e5a8ceSElizabeth Figura 	int objs[4], fd, ret;
94872a651c1SElizabeth Figura 	pthread_t thread;
94972a651c1SElizabeth Figura 
95072a651c1SElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
95172a651c1SElizabeth Figura 	ASSERT_LE(0, fd);
95272a651c1SElizabeth Figura 
95372a651c1SElizabeth Figura 	sem_args.count = 0;
95472a651c1SElizabeth Figura 	sem_args.max = 3;
95572a651c1SElizabeth Figura 	objs[0] = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
95672a651c1SElizabeth Figura 	EXPECT_LE(0, objs[0]);
95772a651c1SElizabeth Figura 
95872a651c1SElizabeth Figura 	mutex_args.owner = 123;
95972a651c1SElizabeth Figura 	mutex_args.count = 1;
96072a651c1SElizabeth Figura 	objs[1] = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
96172a651c1SElizabeth Figura 	EXPECT_LE(0, objs[1]);
96272a651c1SElizabeth Figura 
963a2e5a8ceSElizabeth Figura 	manual_event_args.manual = true;
964a2e5a8ceSElizabeth Figura 	manual_event_args.signaled = true;
965a2e5a8ceSElizabeth Figura 	objs[2] = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &manual_event_args);
966a2e5a8ceSElizabeth Figura 	EXPECT_LE(0, objs[2]);
967a2e5a8ceSElizabeth Figura 
968a2e5a8ceSElizabeth Figura 	auto_event_args.manual = false;
969a2e5a8ceSElizabeth Figura 	auto_event_args.signaled = true;
970a2e5a8ceSElizabeth Figura 	objs[3] = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &auto_event_args);
971a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, objs[3]);
972a2e5a8ceSElizabeth Figura 
97372a651c1SElizabeth Figura 	wait_args.timeout = get_abs_timeout(1000);
97472a651c1SElizabeth Figura 	wait_args.objs = (uintptr_t)objs;
975a2e5a8ceSElizabeth Figura 	wait_args.count = 4;
97672a651c1SElizabeth Figura 	wait_args.owner = 456;
97772a651c1SElizabeth Figura 	thread_args.fd = fd;
97872a651c1SElizabeth Figura 	thread_args.args = &wait_args;
97972a651c1SElizabeth Figura 	thread_args.request = NTSYNC_IOC_WAIT_ALL;
98072a651c1SElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
98172a651c1SElizabeth Figura 	EXPECT_EQ(0, ret);
98272a651c1SElizabeth Figura 
98372a651c1SElizabeth Figura 	ret = wait_for_thread(thread, 100);
98472a651c1SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
98572a651c1SElizabeth Figura 
98672a651c1SElizabeth Figura 	count = 1;
98772a651c1SElizabeth Figura 	ret = release_sem(objs[0], &count);
98872a651c1SElizabeth Figura 	EXPECT_EQ(0, ret);
98972a651c1SElizabeth Figura 	EXPECT_EQ(0, count);
99072a651c1SElizabeth Figura 
99172a651c1SElizabeth Figura 	ret = pthread_tryjoin_np(thread, NULL);
99272a651c1SElizabeth Figura 	EXPECT_EQ(EBUSY, ret);
99372a651c1SElizabeth Figura 
99472a651c1SElizabeth Figura 	check_sem_state(objs[0], 1, 3);
99572a651c1SElizabeth Figura 
99672a651c1SElizabeth Figura 	ret = wait_any(fd, 1, &objs[0], 123, &index);
99772a651c1SElizabeth Figura 	EXPECT_EQ(0, ret);
99872a651c1SElizabeth Figura 	EXPECT_EQ(0, index);
99972a651c1SElizabeth Figura 
100072a651c1SElizabeth Figura 	ret = unlock_mutex(objs[1], 123, &count);
100172a651c1SElizabeth Figura 	EXPECT_EQ(0, ret);
100272a651c1SElizabeth Figura 	EXPECT_EQ(1, count);
100372a651c1SElizabeth Figura 
100472a651c1SElizabeth Figura 	ret = pthread_tryjoin_np(thread, NULL);
100572a651c1SElizabeth Figura 	EXPECT_EQ(EBUSY, ret);
100672a651c1SElizabeth Figura 
100772a651c1SElizabeth Figura 	check_mutex_state(objs[1], 0, 0);
100872a651c1SElizabeth Figura 
1009a2e5a8ceSElizabeth Figura 	ret = ioctl(objs[2], NTSYNC_IOC_EVENT_RESET, &signaled);
1010a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
1011a2e5a8ceSElizabeth Figura 	EXPECT_EQ(1, signaled);
1012a2e5a8ceSElizabeth Figura 
101372a651c1SElizabeth Figura 	count = 2;
101472a651c1SElizabeth Figura 	ret = release_sem(objs[0], &count);
101572a651c1SElizabeth Figura 	EXPECT_EQ(0, ret);
101672a651c1SElizabeth Figura 	EXPECT_EQ(0, count);
1017a2e5a8ceSElizabeth Figura 	check_sem_state(objs[0], 2, 3);
1018a2e5a8ceSElizabeth Figura 
1019a2e5a8ceSElizabeth Figura 	ret = ioctl(objs[3], NTSYNC_IOC_EVENT_RESET, &signaled);
1020a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
1021a2e5a8ceSElizabeth Figura 	EXPECT_EQ(1, signaled);
1022a2e5a8ceSElizabeth Figura 
1023a2e5a8ceSElizabeth Figura 	ret = ioctl(objs[2], NTSYNC_IOC_EVENT_SET, &signaled);
1024a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
1025a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, signaled);
1026a2e5a8ceSElizabeth Figura 
1027a2e5a8ceSElizabeth Figura 	ret = ioctl(objs[3], NTSYNC_IOC_EVENT_SET, &signaled);
1028a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, ret);
1029a2e5a8ceSElizabeth Figura 	EXPECT_EQ(0, signaled);
1030a2e5a8ceSElizabeth Figura 
103172a651c1SElizabeth Figura 	check_sem_state(objs[0], 1, 3);
103272a651c1SElizabeth Figura 	check_mutex_state(objs[1], 1, 456);
1033a2e5a8ceSElizabeth Figura 	check_event_state(objs[2], 1, 1);
1034a2e5a8ceSElizabeth Figura 	check_event_state(objs[3], 0, 0);
103572a651c1SElizabeth Figura 
103672a651c1SElizabeth Figura 	ret = wait_for_thread(thread, 100);
103772a651c1SElizabeth Figura 	EXPECT_EQ(0, ret);
103872a651c1SElizabeth Figura 	EXPECT_EQ(0, thread_args.ret);
103972a651c1SElizabeth Figura 
104072a651c1SElizabeth Figura 	/* delete an object while it's being waited on */
104172a651c1SElizabeth Figura 
104272a651c1SElizabeth Figura 	wait_args.timeout = get_abs_timeout(200);
104372a651c1SElizabeth Figura 	wait_args.owner = 123;
104472a651c1SElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
104572a651c1SElizabeth Figura 	EXPECT_EQ(0, ret);
104672a651c1SElizabeth Figura 
104772a651c1SElizabeth Figura 	ret = wait_for_thread(thread, 100);
104872a651c1SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
104972a651c1SElizabeth Figura 
105072a651c1SElizabeth Figura 	close(objs[0]);
105172a651c1SElizabeth Figura 	close(objs[1]);
1052a2e5a8ceSElizabeth Figura 	close(objs[2]);
1053a2e5a8ceSElizabeth Figura 	close(objs[3]);
105472a651c1SElizabeth Figura 
105572a651c1SElizabeth Figura 	ret = wait_for_thread(thread, 200);
105672a651c1SElizabeth Figura 	EXPECT_EQ(0, ret);
105772a651c1SElizabeth Figura 	EXPECT_EQ(-1, thread_args.ret);
105872a651c1SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, thread_args.err);
105972a651c1SElizabeth Figura 
106072a651c1SElizabeth Figura 	close(fd);
106172a651c1SElizabeth Figura }
106272a651c1SElizabeth Figura 
TEST(alert_any)1063dd914e0dSElizabeth Figura TEST(alert_any)
1064dd914e0dSElizabeth Figura {
1065dd914e0dSElizabeth Figura 	struct ntsync_event_args event_args = {0};
1066c52b9cb1SElizabeth Figura 	struct ntsync_wait_args wait_args = {0};
1067dd914e0dSElizabeth Figura 	struct ntsync_sem_args sem_args = {0};
1068dd914e0dSElizabeth Figura 	__u32 index, count, signaled;
1069c52b9cb1SElizabeth Figura 	struct wait_args thread_args;
1070dd914e0dSElizabeth Figura 	int objs[2], event, fd, ret;
1071c52b9cb1SElizabeth Figura 	pthread_t thread;
1072dd914e0dSElizabeth Figura 
1073dd914e0dSElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
1074dd914e0dSElizabeth Figura 	ASSERT_LE(0, fd);
1075dd914e0dSElizabeth Figura 
1076dd914e0dSElizabeth Figura 	sem_args.count = 0;
1077dd914e0dSElizabeth Figura 	sem_args.max = 2;
1078dd914e0dSElizabeth Figura 	objs[0] = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
1079dd914e0dSElizabeth Figura 	EXPECT_LE(0, objs[0]);
1080dd914e0dSElizabeth Figura 
1081dd914e0dSElizabeth Figura 	sem_args.count = 1;
1082dd914e0dSElizabeth Figura 	sem_args.max = 2;
1083dd914e0dSElizabeth Figura 	objs[1] = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
1084dd914e0dSElizabeth Figura 	EXPECT_LE(0, objs[1]);
1085dd914e0dSElizabeth Figura 
1086dd914e0dSElizabeth Figura 	event_args.manual = true;
1087dd914e0dSElizabeth Figura 	event_args.signaled = true;
1088dd914e0dSElizabeth Figura 	event = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args);
1089dd914e0dSElizabeth Figura 	EXPECT_LE(0, event);
1090dd914e0dSElizabeth Figura 
1091dd914e0dSElizabeth Figura 	ret = wait_any_alert(fd, 0, NULL, 123, event, &index);
1092dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1093dd914e0dSElizabeth Figura 	EXPECT_EQ(0, index);
1094dd914e0dSElizabeth Figura 
1095dd914e0dSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled);
1096dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1097dd914e0dSElizabeth Figura 
1098dd914e0dSElizabeth Figura 	ret = wait_any_alert(fd, 0, NULL, 123, event, &index);
1099dd914e0dSElizabeth Figura 	EXPECT_EQ(-1, ret);
1100dd914e0dSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
1101dd914e0dSElizabeth Figura 
1102dd914e0dSElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled);
1103dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1104dd914e0dSElizabeth Figura 
1105dd914e0dSElizabeth Figura 	ret = wait_any_alert(fd, 2, objs, 123, event, &index);
1106dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1107dd914e0dSElizabeth Figura 	EXPECT_EQ(1, index);
1108dd914e0dSElizabeth Figura 
1109dd914e0dSElizabeth Figura 	ret = wait_any_alert(fd, 2, objs, 123, event, &index);
1110dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1111dd914e0dSElizabeth Figura 	EXPECT_EQ(2, index);
1112dd914e0dSElizabeth Figura 
1113c52b9cb1SElizabeth Figura 	/* test wakeup via alert */
1114c52b9cb1SElizabeth Figura 
1115c52b9cb1SElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled);
1116c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, ret);
1117c52b9cb1SElizabeth Figura 
1118c52b9cb1SElizabeth Figura 	wait_args.timeout = get_abs_timeout(1000);
1119c52b9cb1SElizabeth Figura 	wait_args.objs = (uintptr_t)objs;
1120c52b9cb1SElizabeth Figura 	wait_args.count = 2;
1121c52b9cb1SElizabeth Figura 	wait_args.owner = 123;
1122c52b9cb1SElizabeth Figura 	wait_args.index = 0xdeadbeef;
1123c52b9cb1SElizabeth Figura 	wait_args.alert = event;
1124c52b9cb1SElizabeth Figura 	thread_args.fd = fd;
1125c52b9cb1SElizabeth Figura 	thread_args.args = &wait_args;
1126c52b9cb1SElizabeth Figura 	thread_args.request = NTSYNC_IOC_WAIT_ANY;
1127c52b9cb1SElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
1128c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, ret);
1129c52b9cb1SElizabeth Figura 
1130c52b9cb1SElizabeth Figura 	ret = wait_for_thread(thread, 100);
1131c52b9cb1SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
1132c52b9cb1SElizabeth Figura 
1133c52b9cb1SElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled);
1134c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, ret);
1135c52b9cb1SElizabeth Figura 
1136c52b9cb1SElizabeth Figura 	ret = wait_for_thread(thread, 100);
1137c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, ret);
1138c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, thread_args.ret);
1139c52b9cb1SElizabeth Figura 	EXPECT_EQ(2, wait_args.index);
1140c52b9cb1SElizabeth Figura 
1141dd914e0dSElizabeth Figura 	close(event);
1142dd914e0dSElizabeth Figura 
1143dd914e0dSElizabeth Figura 	/* test with an auto-reset event */
1144dd914e0dSElizabeth Figura 
1145dd914e0dSElizabeth Figura 	event_args.manual = false;
1146dd914e0dSElizabeth Figura 	event_args.signaled = true;
1147dd914e0dSElizabeth Figura 	event = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args);
1148dd914e0dSElizabeth Figura 	EXPECT_LE(0, event);
1149dd914e0dSElizabeth Figura 
1150dd914e0dSElizabeth Figura 	count = 1;
1151dd914e0dSElizabeth Figura 	ret = release_sem(objs[0], &count);
1152dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1153dd914e0dSElizabeth Figura 
1154dd914e0dSElizabeth Figura 	ret = wait_any_alert(fd, 2, objs, 123, event, &index);
1155dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1156dd914e0dSElizabeth Figura 	EXPECT_EQ(0, index);
1157dd914e0dSElizabeth Figura 
1158dd914e0dSElizabeth Figura 	ret = wait_any_alert(fd, 2, objs, 123, event, &index);
1159dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1160dd914e0dSElizabeth Figura 	EXPECT_EQ(2, index);
1161dd914e0dSElizabeth Figura 
1162dd914e0dSElizabeth Figura 	ret = wait_any_alert(fd, 2, objs, 123, event, &index);
1163dd914e0dSElizabeth Figura 	EXPECT_EQ(-1, ret);
1164dd914e0dSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
1165dd914e0dSElizabeth Figura 
1166dd914e0dSElizabeth Figura 	close(event);
1167dd914e0dSElizabeth Figura 
1168dd914e0dSElizabeth Figura 	close(objs[0]);
1169dd914e0dSElizabeth Figura 	close(objs[1]);
1170dd914e0dSElizabeth Figura 
1171dd914e0dSElizabeth Figura 	close(fd);
1172dd914e0dSElizabeth Figura }
1173dd914e0dSElizabeth Figura 
TEST(alert_all)1174dd914e0dSElizabeth Figura TEST(alert_all)
1175dd914e0dSElizabeth Figura {
1176dd914e0dSElizabeth Figura 	struct ntsync_event_args event_args = {0};
1177c52b9cb1SElizabeth Figura 	struct ntsync_wait_args wait_args = {0};
1178dd914e0dSElizabeth Figura 	struct ntsync_sem_args sem_args = {0};
1179c52b9cb1SElizabeth Figura 	struct wait_args thread_args;
1180dd914e0dSElizabeth Figura 	__u32 index, count, signaled;
1181dd914e0dSElizabeth Figura 	int objs[2], event, fd, ret;
1182c52b9cb1SElizabeth Figura 	pthread_t thread;
1183dd914e0dSElizabeth Figura 
1184dd914e0dSElizabeth Figura 	fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
1185dd914e0dSElizabeth Figura 	ASSERT_LE(0, fd);
1186dd914e0dSElizabeth Figura 
1187dd914e0dSElizabeth Figura 	sem_args.count = 2;
1188dd914e0dSElizabeth Figura 	sem_args.max = 2;
1189dd914e0dSElizabeth Figura 	objs[0] = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
1190dd914e0dSElizabeth Figura 	EXPECT_LE(0, objs[0]);
1191dd914e0dSElizabeth Figura 
1192dd914e0dSElizabeth Figura 	sem_args.count = 1;
1193dd914e0dSElizabeth Figura 	sem_args.max = 2;
1194dd914e0dSElizabeth Figura 	objs[1] = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
1195dd914e0dSElizabeth Figura 	EXPECT_LE(0, objs[1]);
1196dd914e0dSElizabeth Figura 
1197dd914e0dSElizabeth Figura 	event_args.manual = true;
1198dd914e0dSElizabeth Figura 	event_args.signaled = true;
1199dd914e0dSElizabeth Figura 	event = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args);
1200dd914e0dSElizabeth Figura 	EXPECT_LE(0, event);
1201dd914e0dSElizabeth Figura 
1202dd914e0dSElizabeth Figura 	ret = wait_all_alert(fd, 2, objs, 123, event, &index);
1203dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1204dd914e0dSElizabeth Figura 	EXPECT_EQ(0, index);
1205dd914e0dSElizabeth Figura 
1206dd914e0dSElizabeth Figura 	ret = wait_all_alert(fd, 2, objs, 123, event, &index);
1207dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1208dd914e0dSElizabeth Figura 	EXPECT_EQ(2, index);
1209dd914e0dSElizabeth Figura 
1210c52b9cb1SElizabeth Figura 	/* test wakeup via alert */
1211c52b9cb1SElizabeth Figura 
1212c52b9cb1SElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_RESET, &signaled);
1213c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, ret);
1214c52b9cb1SElizabeth Figura 
1215c52b9cb1SElizabeth Figura 	wait_args.timeout = get_abs_timeout(1000);
1216c52b9cb1SElizabeth Figura 	wait_args.objs = (uintptr_t)objs;
1217c52b9cb1SElizabeth Figura 	wait_args.count = 2;
1218c52b9cb1SElizabeth Figura 	wait_args.owner = 123;
1219c52b9cb1SElizabeth Figura 	wait_args.index = 0xdeadbeef;
1220c52b9cb1SElizabeth Figura 	wait_args.alert = event;
1221c52b9cb1SElizabeth Figura 	thread_args.fd = fd;
1222c52b9cb1SElizabeth Figura 	thread_args.args = &wait_args;
1223c52b9cb1SElizabeth Figura 	thread_args.request = NTSYNC_IOC_WAIT_ALL;
1224c52b9cb1SElizabeth Figura 	ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
1225c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, ret);
1226c52b9cb1SElizabeth Figura 
1227c52b9cb1SElizabeth Figura 	ret = wait_for_thread(thread, 100);
1228c52b9cb1SElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, ret);
1229c52b9cb1SElizabeth Figura 
1230c52b9cb1SElizabeth Figura 	ret = ioctl(event, NTSYNC_IOC_EVENT_SET, &signaled);
1231c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, ret);
1232c52b9cb1SElizabeth Figura 
1233c52b9cb1SElizabeth Figura 	ret = wait_for_thread(thread, 100);
1234c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, ret);
1235c52b9cb1SElizabeth Figura 	EXPECT_EQ(0, thread_args.ret);
1236c52b9cb1SElizabeth Figura 	EXPECT_EQ(2, wait_args.index);
1237c52b9cb1SElizabeth Figura 
1238dd914e0dSElizabeth Figura 	close(event);
1239dd914e0dSElizabeth Figura 
1240dd914e0dSElizabeth Figura 	/* test with an auto-reset event */
1241dd914e0dSElizabeth Figura 
1242dd914e0dSElizabeth Figura 	event_args.manual = false;
1243dd914e0dSElizabeth Figura 	event_args.signaled = true;
1244dd914e0dSElizabeth Figura 	event = ioctl(fd, NTSYNC_IOC_CREATE_EVENT, &event_args);
1245dd914e0dSElizabeth Figura 	EXPECT_LE(0, event);
1246dd914e0dSElizabeth Figura 
1247dd914e0dSElizabeth Figura 	count = 2;
1248dd914e0dSElizabeth Figura 	ret = release_sem(objs[1], &count);
1249dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1250dd914e0dSElizabeth Figura 
1251dd914e0dSElizabeth Figura 	ret = wait_all_alert(fd, 2, objs, 123, event, &index);
1252dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1253dd914e0dSElizabeth Figura 	EXPECT_EQ(0, index);
1254dd914e0dSElizabeth Figura 
1255dd914e0dSElizabeth Figura 	ret = wait_all_alert(fd, 2, objs, 123, event, &index);
1256dd914e0dSElizabeth Figura 	EXPECT_EQ(0, ret);
1257dd914e0dSElizabeth Figura 	EXPECT_EQ(2, index);
1258dd914e0dSElizabeth Figura 
1259dd914e0dSElizabeth Figura 	ret = wait_all_alert(fd, 2, objs, 123, event, &index);
1260dd914e0dSElizabeth Figura 	EXPECT_EQ(-1, ret);
1261dd914e0dSElizabeth Figura 	EXPECT_EQ(ETIMEDOUT, errno);
1262dd914e0dSElizabeth Figura 
1263dd914e0dSElizabeth Figura 	close(event);
1264dd914e0dSElizabeth Figura 
1265dd914e0dSElizabeth Figura 	close(objs[0]);
1266dd914e0dSElizabeth Figura 	close(objs[1]);
1267dd914e0dSElizabeth Figura 
1268dd914e0dSElizabeth Figura 	close(fd);
1269dd914e0dSElizabeth Figura }
1270dd914e0dSElizabeth Figura 
1271*a22860e5SElizabeth Figura #define STRESS_LOOPS 10000
1272*a22860e5SElizabeth Figura #define STRESS_THREADS 4
1273*a22860e5SElizabeth Figura 
1274*a22860e5SElizabeth Figura static unsigned int stress_counter;
1275*a22860e5SElizabeth Figura static int stress_device, stress_start_event, stress_mutex;
1276*a22860e5SElizabeth Figura 
stress_thread(void * arg)1277*a22860e5SElizabeth Figura static void *stress_thread(void *arg)
1278*a22860e5SElizabeth Figura {
1279*a22860e5SElizabeth Figura 	struct ntsync_wait_args wait_args = {0};
1280*a22860e5SElizabeth Figura 	__u32 index, count, i;
1281*a22860e5SElizabeth Figura 	int ret;
1282*a22860e5SElizabeth Figura 
1283*a22860e5SElizabeth Figura 	wait_args.timeout = UINT64_MAX;
1284*a22860e5SElizabeth Figura 	wait_args.count = 1;
1285*a22860e5SElizabeth Figura 	wait_args.objs = (uintptr_t)&stress_start_event;
1286*a22860e5SElizabeth Figura 	wait_args.owner = gettid();
1287*a22860e5SElizabeth Figura 	wait_args.index = 0xdeadbeef;
1288*a22860e5SElizabeth Figura 
1289*a22860e5SElizabeth Figura 	ioctl(stress_device, NTSYNC_IOC_WAIT_ANY, &wait_args);
1290*a22860e5SElizabeth Figura 
1291*a22860e5SElizabeth Figura 	wait_args.objs = (uintptr_t)&stress_mutex;
1292*a22860e5SElizabeth Figura 
1293*a22860e5SElizabeth Figura 	for (i = 0; i < STRESS_LOOPS; ++i) {
1294*a22860e5SElizabeth Figura 		ioctl(stress_device, NTSYNC_IOC_WAIT_ANY, &wait_args);
1295*a22860e5SElizabeth Figura 
1296*a22860e5SElizabeth Figura 		++stress_counter;
1297*a22860e5SElizabeth Figura 
1298*a22860e5SElizabeth Figura 		unlock_mutex(stress_mutex, wait_args.owner, &count);
1299*a22860e5SElizabeth Figura 	}
1300*a22860e5SElizabeth Figura 
1301*a22860e5SElizabeth Figura 	return NULL;
1302*a22860e5SElizabeth Figura }
1303*a22860e5SElizabeth Figura 
TEST(stress_wait)1304*a22860e5SElizabeth Figura TEST(stress_wait)
1305*a22860e5SElizabeth Figura {
1306*a22860e5SElizabeth Figura 	struct ntsync_event_args event_args;
1307*a22860e5SElizabeth Figura 	struct ntsync_mutex_args mutex_args;
1308*a22860e5SElizabeth Figura 	pthread_t threads[STRESS_THREADS];
1309*a22860e5SElizabeth Figura 	__u32 signaled, i;
1310*a22860e5SElizabeth Figura 	int ret;
1311*a22860e5SElizabeth Figura 
1312*a22860e5SElizabeth Figura 	stress_device = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
1313*a22860e5SElizabeth Figura 	ASSERT_LE(0, stress_device);
1314*a22860e5SElizabeth Figura 
1315*a22860e5SElizabeth Figura 	mutex_args.owner = 0;
1316*a22860e5SElizabeth Figura 	mutex_args.count = 0;
1317*a22860e5SElizabeth Figura 	stress_mutex = ioctl(stress_device, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
1318*a22860e5SElizabeth Figura 	EXPECT_LE(0, stress_mutex);
1319*a22860e5SElizabeth Figura 
1320*a22860e5SElizabeth Figura 	event_args.manual = 1;
1321*a22860e5SElizabeth Figura 	event_args.signaled = 0;
1322*a22860e5SElizabeth Figura 	stress_start_event = ioctl(stress_device, NTSYNC_IOC_CREATE_EVENT, &event_args);
1323*a22860e5SElizabeth Figura 	EXPECT_LE(0, stress_start_event);
1324*a22860e5SElizabeth Figura 
1325*a22860e5SElizabeth Figura 	for (i = 0; i < STRESS_THREADS; ++i)
1326*a22860e5SElizabeth Figura 		pthread_create(&threads[i], NULL, stress_thread, NULL);
1327*a22860e5SElizabeth Figura 
1328*a22860e5SElizabeth Figura 	ret = ioctl(stress_start_event, NTSYNC_IOC_EVENT_SET, &signaled);
1329*a22860e5SElizabeth Figura 	EXPECT_EQ(0, ret);
1330*a22860e5SElizabeth Figura 
1331*a22860e5SElizabeth Figura 	for (i = 0; i < STRESS_THREADS; ++i) {
1332*a22860e5SElizabeth Figura 		ret = pthread_join(threads[i], NULL);
1333*a22860e5SElizabeth Figura 		EXPECT_EQ(0, ret);
1334*a22860e5SElizabeth Figura 	}
1335*a22860e5SElizabeth Figura 
1336*a22860e5SElizabeth Figura 	EXPECT_EQ(STRESS_LOOPS * STRESS_THREADS, stress_counter);
1337*a22860e5SElizabeth Figura 
1338*a22860e5SElizabeth Figura 	close(stress_start_event);
1339*a22860e5SElizabeth Figura 	close(stress_mutex);
1340*a22860e5SElizabeth Figura 	close(stress_device);
1341*a22860e5SElizabeth Figura }
1342*a22860e5SElizabeth Figura 
13437f853a25SElizabeth Figura TEST_HARNESS_MAIN
1344