summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorJing Chen <chjing@google.com>2021-02-11 12:19:48 -0800
committergVisor bot <gvisor-bot@google.com>2021-02-11 12:21:59 -0800
commitc833eed80a4ceaf9da852ef361dd5f4864eb647d (patch)
tree154855a9bc74b07c6b9c7e04608668cf6b25068d /test
parentae8d966f5af0bba9978a1aedac64038ef65a4cc9 (diff)
Implement semtimedop.
PiperOrigin-RevId: 357031904
Diffstat (limited to 'test')
-rw-r--r--test/syscalls/linux/semaphore.cc58
1 files changed, 58 insertions, 0 deletions
diff --git a/test/syscalls/linux/semaphore.cc b/test/syscalls/linux/semaphore.cc
index 0530fce44..b8f6ced30 100644
--- a/test/syscalls/linux/semaphore.cc
+++ b/test/syscalls/linux/semaphore.cc
@@ -116,6 +116,41 @@ TEST(SemaphoreTest, SemOpSingleNoBlock) {
ASSERT_THAT(semop(sem.get(), nullptr, 0), SyscallFailsWithErrno(EINVAL));
}
+// Tests simple timed operations that shouldn't block in a single-thread.
+TEST(SemaphoreTest, SemTimedOpSingleNoBlock) {
+ AutoSem sem(semget(IPC_PRIVATE, 1, 0600 | IPC_CREAT));
+ ASSERT_THAT(sem.get(), SyscallSucceeds());
+
+ struct sembuf buf = {};
+ buf.sem_op = 1;
+ struct timespec timeout = {};
+ // 50 milliseconds.
+ timeout.tv_nsec = 5e7;
+ ASSERT_THAT(semtimedop(sem.get(), &buf, 1, &timeout), SyscallSucceeds());
+
+ buf.sem_op = -1;
+ EXPECT_THAT(semtimedop(sem.get(), &buf, 1, &timeout), SyscallSucceeds());
+
+ buf.sem_op = 0;
+ EXPECT_THAT(semtimedop(sem.get(), &buf, 1, &timeout), SyscallSucceeds());
+
+ // Error cases with invalid values.
+ EXPECT_THAT(semtimedop(sem.get() + 1, &buf, 1, &timeout),
+ SyscallFailsWithErrno(EINVAL));
+
+ buf.sem_num = 1;
+ EXPECT_THAT(semtimedop(sem.get(), &buf, 1, &timeout),
+ SyscallFailsWithErrno(EFBIG));
+ buf.sem_num = 0;
+
+ EXPECT_THAT(semtimedop(sem.get(), nullptr, 0, &timeout),
+ SyscallFailsWithErrno(EINVAL));
+
+ timeout.tv_nsec = 1e9;
+ EXPECT_THAT(semtimedop(sem.get(), &buf, 0, &timeout),
+ SyscallFailsWithErrno(EINVAL));
+}
+
// Tests multiple operations that shouldn't block in a single-thread.
TEST(SemaphoreTest, SemOpMultiNoBlock) {
AutoSem sem(semget(IPC_PRIVATE, 4, 0600 | IPC_CREAT));
@@ -184,6 +219,29 @@ TEST(SemaphoreTest, SemOpBlock) {
blocked.store(0);
}
+// Makes a best effort attempt to ensure that operation would be timeout when
+// being blocked.
+TEST(SemaphoreTest, SemTimedOpBlock) {
+ AutoSem sem(semget(IPC_PRIVATE, 1, 0600 | IPC_CREAT));
+ ASSERT_THAT(sem.get(), SyscallSucceeds());
+
+ ScopedThread th([&sem] {
+ absl::SleepFor(absl::Milliseconds(100));
+
+ struct sembuf buf = {};
+ buf.sem_op = 1;
+ ASSERT_THAT(RetryEINTR(semop)(sem.get(), &buf, 1), SyscallSucceeds());
+ });
+
+ struct sembuf buf = {};
+ buf.sem_op = -1;
+ struct timespec timeout = {};
+ timeout.tv_nsec = 5e7;
+ // semtimedop reaches the time limit, it fails with errno EAGAIN.
+ ASSERT_THAT(RetryEINTR(semtimedop)(sem.get(), &buf, 1, &timeout),
+ SyscallFailsWithErrno(EAGAIN));
+}
+
// Tests that IPC_NOWAIT returns with no wait.
TEST(SemaphoreTest, SemOpNoBlock) {
AutoSem sem(semget(IPC_PRIVATE, 1, 0600 | IPC_CREAT));