Index: libc/config/linux/api.td =================================================================== --- libc/config/linux/api.td +++ libc/config/linux/api.td @@ -133,3 +133,58 @@ "munmap", ]; } + +def SignalAPI : PublicAPI<"signal.h"> { + let Macros = [ + MacroDefineIfNot<"SIG_BLOCK", "0">, + MacroDefineIfNot<"SIG_UNBLOCK", "1">, + MacroDefineIfNot<"SIG_SETMASK", "2">, + + // We use so these should be defined. + MacroDefineIfNot<"NSIG", "64">, + + MacroDefineIfNot<"SIGHUP", "1">, + MacroDefineIfNot<"SIGINT", "2">, + MacroDefineIfNot<"SIGQUIT", "3">, + MacroDefineIfNot<"SIGILL", "4">, + MacroDefineIfNot<"SIGTRAP", "5">, + MacroDefineIfNot<"SIGABRT", "6">, + MacroDefineIfNot<"SIGIOT", "6">, + MacroDefineIfNot<"SIGBUS", "7">, + MacroDefineIfNot<"SIGFPE", "8">, + MacroDefineIfNot<"SIGKILL", "9">, + MacroDefineIfNot<"SIGUSR1", "10">, + MacroDefineIfNot<"SIGSEGV", "11">, + MacroDefineIfNot<"SIGUSR2", "12">, + MacroDefineIfNot<"SIGPIPE", "13">, + MacroDefineIfNot<"SIGALRM", "14">, + MacroDefineIfNot<"SIGTERM", "15">, + MacroDefineIfNot<"SIGSTKFLT", "16">, + MacroDefineIfNot<"SIGCHLD", "17">, + MacroDefineIfNot<"SIGCONT", "18">, + MacroDefineIfNot<"SIGSTOP", "19">, + MacroDefineIfNot<"SIGTSTP", "20">, + MacroDefineIfNot<"SIGTTIN", "21">, + MacroDefineIfNot<"SIGTTOU", "22">, + MacroDefineIfNot<"SIGURG", "23">, + MacroDefineIfNot<"SIGXCPU", "24">, + MacroDefineIfNot<"SIGXFSZ", "25">, + MacroDefineIfNot<"SIGVTALRM", "26">, + MacroDefineIfNot<"SIGPROF", "27">, + MacroDefineIfNot<"SIGWINCH", "28">, + MacroDefineIfNot<"SIGIO", "29">, + MacroDefineIfNot<"SIGPOLL", "SIGIO">, + MacroDefineIfNot<"SIGPWR", "30">, + MacroDefineIfNot<"SIGSYS", "31">, + MacroDefineIfNot<"SIGUNUSED", "31">, + ]; + + let TypeDeclarations = [ + // SigSetT, + SizeT // This is needed by . + ]; + + let Functions = [ + "raise" + ]; +} Index: libc/config/linux/signal.h.in =================================================================== --- /dev/null +++ libc/config/linux/signal.h.in @@ -0,0 +1,11 @@ +//===---------------- Linux specific signal.h definitions -----------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +%%begin() + +#include Index: libc/include/CMakeLists.txt =================================================================== --- libc/include/CMakeLists.txt +++ libc/include/CMakeLists.txt @@ -45,6 +45,17 @@ ../config/${LIBC_TARGET_OS}/errno.h.in ) +add_gen_header( + signal_h + DEF_FILE signal.h.def + PARAMS + platform_signal=../config/${LIBC_TARGET_OS}/signal.h.in + GEN_HDR signal.h + DATA_FILES + ../config/${LIBC_TARGET_OS}/signal.h.in +) + + # TODO: Not all platforms will have a include/sys directory. Add the sys # directory and the targets for sys/*.h files conditional to the OS requiring # them. Index: libc/include/signal.h.def =================================================================== --- /dev/null +++ libc/include/signal.h.def @@ -0,0 +1,18 @@ +//===---------------- C standard library header signal.h ------------------===// +// +// 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_SIGNAL_H +#define LLVM_LIBC_SIGNAL_H + +#include <__llvm-libc-common.h> + +%%public_api() + +%%include_file(${platform_signal}) + +#endif // LLVM_LIBC_SIGNAL_H Index: libc/lib/CMakeLists.txt =================================================================== --- libc/lib/CMakeLists.txt +++ libc/lib/CMakeLists.txt @@ -12,6 +12,9 @@ # sys/mman.h entrypoints mmap munmap + + # signal.h entrypoints + raise ) add_entrypoint_library( Index: libc/spec/linux.td =================================================================== --- libc/spec/linux.td +++ libc/spec/linux.td @@ -67,8 +67,53 @@ [] // Functions >; + HeaderSpec Signal = HeaderSpec< + "signal.h", + [ + Macro<"NSIG">, + + Macro<"SIGHUP">, + Macro<"SIGINT">, + Macro<"SIGQUIT">, + Macro<"SIGILL">, + Macro<"SIGTRAP">, + Macro<"SIGABRT">, + Macro<"SIGIOT">, + Macro<"SIGBUS">, + Macro<"SIGFPE">, + Macro<"SIGKILL">, + Macro<"SIGUSR1">, + Macro<"SIGSEGV">, + Macro<"SIGUSR2">, + Macro<"SIGPIPE">, + Macro<"SIGALRM">, + Macro<"SIGTERM">, + Macro<"SIGSTKFLT">, + Macro<"SIGCHLD">, + Macro<"SIGCONT">, + Macro<"SIGSTOP">, + Macro<"SIGTSTP">, + Macro<"SIGTTIN">, + Macro<"SIGTTOU">, + Macro<"SIGURG">, + Macro<"SIGXCPU">, + Macro<"SIGXFSZ">, + Macro<"SIGVTALRM">, + Macro<"SIGPROF">, + Macro<"SIGWINCH">, + Macro<"SIGIO">, + Macro<"SIGPOLL">, + Macro<"SIGPWR">, + Macro<"SIGSYS">, + Macro<"SIGUNUSED">, + ], + [], // Types + [] // Functions + >; + let Headers = [ Errno, SysMMan, + Signal ]; } Index: libc/spec/stdc.td =================================================================== --- libc/spec/stdc.td +++ libc/spec/stdc.td @@ -179,10 +179,34 @@ [] // Functions >; + HeaderSpec Signal = HeaderSpec< + "signal.h", + [ + Macro<"SIG_BLOCK">, + Macro<"SIG_UNBLOCK">, + Macro<"SIG_SETMASK">, + + Macro<"SIGABRT">, + Macro<"SIGFPE">, + Macro<"SIGILL">, + Macro<"SIGINT">, + Macro<"SIGSEGV">, + Macro<"SIGTERM"> + ], + [ + NamedType<"sigset_t">, + SizeTType + ], // Types + [ + FunctionSpec<"raise", RetValSpec, [ArgSpec]>, + ] + >; + let Headers = [ Errno, Math, String, StdIO, + Signal, ]; } Index: libc/src/CMakeLists.txt =================================================================== --- libc/src/CMakeLists.txt +++ libc/src/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(errno) add_subdirectory(math) +add_subdirectory(signal) add_subdirectory(string) # TODO: Add this target conditional to the target OS. add_subdirectory(sys) Index: libc/src/signal/CMakeLists.txt =================================================================== --- /dev/null +++ libc/src/signal/CMakeLists.txt @@ -0,0 +1,4 @@ + +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${LIBC_TARGET_OS}) +endif() Index: libc/src/signal/linux/CMakeLists.txt =================================================================== --- /dev/null +++ libc/src/signal/linux/CMakeLists.txt @@ -0,0 +1,14 @@ + +add_entrypoint_object( + raise + SRCS + raise.cpp + HDRS + signal.h + ../raise.h + DEPENDS + sys_syscall_h + linux_syscall_h + __errno_location + signal_h +) Index: libc/src/signal/linux/raise.cpp =================================================================== --- /dev/null +++ libc/src/signal/linux/raise.cpp @@ -0,0 +1,26 @@ +//===------------------ Linux implementation of signal --------------------===// +// +// 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/raise.h" +#include "src/signal/linux/signal.h" + +#include "src/__support/common.h" + +namespace __llvm_libc { + +int LLVM_LIBC_ENTRYPOINT(raise)(int sig) { + sigset_t sigset; + __llvm_libc::block_all_signals(&sigset); + long pid = __llvm_libc::syscall(SYS_getpid); + long tid = __llvm_libc::syscall(SYS_gettid); + int ret = __llvm_libc::syscall(SYS_tgkill, pid, tid, sig); + __llvm_libc::restore_signals(&sigset); + return ret; +} + +} // namespace __llvm_libc Index: libc/src/signal/linux/signal.h =================================================================== --- /dev/null +++ libc/src/signal/linux/signal.h @@ -0,0 +1,36 @@ +//===----------------- Internal header for Linux signals ------------------===// +// +// 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_LINUX_SIGNAL_H +#define LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_H + +#include "config/linux/syscall.h" // For internal syscall function. +#include "include/sys/syscall.h" // For syscall numbers. + +#include "include/signal.h" + +static_assert(sizeof(sigset_t) * 8 <= NSIG, "sigset_t cannot hold all signals"); + +namespace __llvm_libc { + +// All bits set meaning all signals. +const static sigset_t all_set = -1; + +static inline int block_all_signals(sigset_t *set) { + return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_BLOCK, &all_set, set, + sizeof(sigset_t)); +} + +static inline int restore_signals(const sigset_t *set) { + return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_SETMASK, set, nullptr, + sizeof(sigset_t)); +} + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_H Index: libc/src/signal/raise.h =================================================================== --- /dev/null +++ libc/src/signal/raise.h @@ -0,0 +1,20 @@ +//===------------- Implementation header for raise function ------ *-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_RAISE_H +#define LLVM_LIBC_SRC_SIGNAL_RAISE_H + +#include "include/signal.h" + +namespace __llvm_libc { + +int raise(int sig); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_SIGNAL_RAISE_H Index: libc/test/src/CMakeLists.txt =================================================================== --- libc/test/src/CMakeLists.txt +++ libc/test/src/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(errno) +add_subdirectory(signal) add_subdirectory(string) add_subdirectory(sys) Index: libc/test/src/signal/CMakeLists.txt =================================================================== --- /dev/null +++ libc/test/src/signal/CMakeLists.txt @@ -0,0 +1,11 @@ +add_libc_testsuite(libc_signal_unittests) + +add_libc_unittest( + raise_test + SUITE + libc_signal_unittests + SRCS + raise_test.cpp + DEPENDS + signal_h +) Index: libc/test/src/signal/raise_test.cpp =================================================================== --- /dev/null +++ libc/test/src/signal/raise_test.cpp @@ -0,0 +1,16 @@ +//===----------------------- Unittests for raise --------------------------===// +// +// 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/signal.h" +#include "utils/UnitTest/Test.h" + +TEST(SignalTest, Raise) { + // SIGCONT is ingored unless stopped, so we can use it to check the return + // value of raise without needing to block. + EXPECT_EQ(raise(SIGCONT), 0); +}