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