[libc] Add sigfillset and sigdelset

Summary: Add's `sigfillset` and `sigdelset` which will be used in D76676.

Reviewers: sivachandra, PaulkaToast

Reviewed By: sivachandra

Subscribers: mgorny, MaskRay, tschuett, libc-commits

Differential Revision: https://reviews.llvm.org/D76936
This commit is contained in:
Alex Brachet 2020-04-01 15:07:49 -04:00
parent 3d90048791
commit 123a5328f9
9 changed files with 224 additions and 7 deletions

View File

@ -94,3 +94,29 @@ add_entrypoint_object(
sigaction
signal_h
)
add_entrypoint_object(
sigfillset
SRCS
sigfillset.cpp
HDRS
signal.h
../sigfillset.h
DEPENDS
__errno_location
errno_h
signal_h
)
add_entrypoint_object(
sigdelset
SRCS
sigdelset.cpp
HDRS
signal.h
../sigdelset.h
DEPENDS
__errno_location
errno_h
signal_h
)

View File

@ -0,0 +1,28 @@
//===----------------- Linux implementation of sigdelset ------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "src/signal/sigdelset.h"
#include "include/errno.h"
#include "src/errno/llvmlibc_errno.h"
#include "src/signal/linux/signal.h"
#include "src/__support/common.h"
namespace __llvm_libc {
int LLVM_LIBC_ENTRYPOINT(sigdelset)(sigset_t *set, int signum) {
if (!set || (unsigned)(signum - 1) >= (8 * sizeof(sigset_t))) {
llvmlibc_errno = EINVAL;
return -1;
}
auto *sigset = reinterpret_cast<__llvm_libc::Sigset *>(set);
sigset->delset(signum);
return 0;
}
} // namespace __llvm_libc

View File

@ -0,0 +1,28 @@
//===----------------- Linux implementation of sigfillset -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "src/signal/sigfillset.h"
#include "include/errno.h"
#include "src/errno/llvmlibc_errno.h"
#include "src/signal/linux/signal.h"
#include "src/__support/common.h"
namespace __llvm_libc {
int LLVM_LIBC_ENTRYPOINT(sigfillset)(sigset_t *set) {
if (!set) {
llvmlibc_errno = EINVAL;
return -1;
}
auto *sigset = reinterpret_cast<__llvm_libc::Sigset *>(set);
*sigset = __llvm_libc::Sigset::fullset();
return 0;
}
} // namespace __llvm_libc

View File

@ -26,9 +26,9 @@ struct Sigset {
constexpr static Sigset fullset() { return {-1UL}; }
constexpr static Sigset emptySet() { return {0}; }
constexpr void addset(int signal) {
nativeSigset |= (1L << (signal - 1));
}
constexpr void addset(int signal) { nativeSigset |= (1L << (signal - 1)); }
constexpr void delset(int signal) { nativeSigset &= ~(1L << (signal - 1)); }
operator sigset_t() const { return nativeSigset; }
};
@ -39,16 +39,15 @@ static inline int block_all_signals(Sigset &set) {
sigset_t nativeSigset = all;
sigset_t oldSet = set;
int ret = __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_BLOCK, &nativeSigset,
&oldSet, sizeof(sigset_t));
&oldSet, sizeof(sigset_t));
set = {oldSet};
return ret;
}
static inline int restore_signals(const Sigset &set) {
sigset_t nativeSigset = set;
return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_SETMASK,
&nativeSigset, nullptr,
sizeof(sigset_t));
return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_SETMASK, &nativeSigset,
nullptr, sizeof(sigset_t));
}
} // namespace __llvm_libc

View File

@ -0,0 +1,20 @@
//===------------- Implementation header for sigdelset ---------*- C++ -*--===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC_SIGNAL_SIGDELSET_H
#define LLVM_LIBC_SRC_SIGNAL_SIGDELSET_H
#include "include/signal.h"
namespace __llvm_libc {
int sigdelset(sigset_t *set, int signum);
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_SIGNAL_SIGDELSET_H

View File

@ -0,0 +1,20 @@
//===------------- Implementation header for sigfillset --------*- C++ -*--===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC_SIGNAL_SIGFILLSET_H
#define LLVM_LIBC_SRC_SIGNAL_SIGFILLSET_H
#include "include/signal.h"
namespace __llvm_libc {
int sigfillset(sigset_t *set);
} // namespace __llvm_libc
#endif // LLVM_LIBC_SRC_SIGNAL_SIGFILLSET_H

View File

@ -66,3 +66,34 @@ add_libc_unittest(
__errno_location
errno_h
)
add_libc_unittest(
sigfillset_test
SUITE
libc_signal_unittests
SRCS
sigfillset_test.cpp
DEPENDS
sigfillset
sigprocmask
signal_h
raise
errno_h
__errno_location
)
add_libc_unittest(
sigdelset_test
SUITE
libc_signal_unittests
SRCS
sigdelset_test.cpp
DEPENDS
sigdelset
sigfillset
sigprocmask
signal_h
raise
errno_h
__errno_location
)

View File

@ -0,0 +1,36 @@
//===--------------------- Unittests for sigdelset ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "include/errno.h"
#include "include/signal.h"
#include "src/signal/raise.h"
#include "src/signal/sigdelset.h"
#include "src/signal/sigfillset.h"
#include "src/signal/sigprocmask.h"
#include "utils/UnitTest/ErrnoSetterMatcher.h"
#include "utils/UnitTest/Test.h"
TEST(Sigdelset, Invalid) {
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
// Invalid set.
EXPECT_THAT(__llvm_libc::sigdelset(nullptr, SIGUSR1), Fails(EINVAL));
sigset_t set;
// Valid set, invalid signum.
EXPECT_THAT(__llvm_libc::sigdelset(&set, -1), Fails(EINVAL));
}
TEST(Sigdelset, UnblockOne) {
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
sigset_t set;
EXPECT_THAT(__llvm_libc::sigfillset(&set), Succeeds());
EXPECT_THAT(__llvm_libc::sigdelset(&set, SIGUSR1), Succeeds());
EXPECT_THAT(__llvm_libc::sigprocmask(SIG_SETMASK, &set, nullptr), Succeeds());
EXPECT_DEATH([] { __llvm_libc::raise(SIGUSR1); }, SIGUSR1);
}

View File

@ -0,0 +1,29 @@
//===-------------------- Unittests for sigfillset ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "include/errno.h"
#include "include/signal.h"
#include "src/signal/raise.h"
#include "src/signal/sigfillset.h"
#include "src/signal/sigprocmask.h"
#include "utils/UnitTest/ErrnoSetterMatcher.h"
#include "utils/UnitTest/Test.h"
TEST(Sigfillset, Invalid) {
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
EXPECT_THAT(__llvm_libc::sigfillset(nullptr), Fails(EINVAL));
}
TEST(Sigfillset, BlocksAll) {
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
sigset_t set;
EXPECT_THAT(__llvm_libc::sigfillset(&set), Succeeds());
EXPECT_THAT(__llvm_libc::sigprocmask(SIG_SETMASK, &set, nullptr), Succeeds());
EXPECT_EXITS([] { __llvm_libc::raise(SIGUSR1); }, 0);
}