From c833eed80a4ceaf9da852ef361dd5f4864eb647d Mon Sep 17 00:00:00 2001 From: Jing Chen Date: Thu, 11 Feb 2021 12:19:48 -0800 Subject: Implement semtimedop. PiperOrigin-RevId: 357031904 --- test/syscalls/linux/semaphore.cc | 58 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'test/syscalls') 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)); -- cgit v1.2.3