[libc-commits] [libc] 5d2baa9 - [libc] Add Initial Support for Signals
Alex Brachet via libc-commits
libc-commits at lists.llvm.org
Thu Feb 20 11:06:57 PST 2020
Author: Alex Brachet
Date: 2020-02-20T14:05:34-05:00
New Revision: 5d2baa956ac3784e3956e35f610e118cacc7128b
URL: https://github.com/llvm/llvm-project/commit/5d2baa956ac3784e3956e35f610e118cacc7128b
DIFF: https://github.com/llvm/llvm-project/commit/5d2baa956ac3784e3956e35f610e118cacc7128b.diff
LOG: [libc] Add Initial Support for Signals
Summary:
This patch adds signal support on Linux. The current implementation gets the SIG* macros and types like `sigset_t` from <linux/signals.h>
This patch also adds raise(3), and internal routines `block_all_signals` and `restore_signals`
Reviewers: sivachandra, MaskRay, gchatelet
Reviewed By: sivachandra
Subscribers: libc-commits, mgorny, tschuett
Differential Revision: https://reviews.llvm.org/D74528
Added:
libc/config/linux/signal.h.in
libc/include/signal.h.def
libc/src/signal/CMakeLists.txt
libc/src/signal/linux/CMakeLists.txt
libc/src/signal/linux/raise.cpp
libc/src/signal/linux/signal.h
libc/src/signal/raise.h
libc/test/src/signal/CMakeLists.txt
libc/test/src/signal/raise_test.cpp
Modified:
libc/config/linux/api.td
libc/include/CMakeLists.txt
libc/lib/CMakeLists.txt
libc/spec/linux.td
libc/spec/stdc.td
libc/src/CMakeLists.txt
libc/test/src/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 8376eefb3ac9..3d7faa75bf69 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -133,3 +133,13 @@ def SysMManAPI : PublicAPI<"sys/mman.h"> {
"munmap",
];
}
+
+def SignalAPI : PublicAPI<"signal.h"> {
+ let TypeDeclarations = [
+ SizeT, // This is needed by <linux/signal.h>.
+ ];
+
+ let Functions = [
+ "raise",
+ ];
+}
diff --git a/libc/config/linux/signal.h.in b/libc/config/linux/signal.h.in
new file mode 100644
index 000000000000..1c2a30779f2b
--- /dev/null
+++ b/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 <linux/signal.h>
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 8558d7586b57..1ff9e7829097 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -45,6 +45,16 @@ add_gen_header(
../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.
diff --git a/libc/include/signal.h.def b/libc/include/signal.h.def
new file mode 100644
index 000000000000..9e4209551374
--- /dev/null
+++ b/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
diff --git a/libc/lib/CMakeLists.txt b/libc/lib/CMakeLists.txt
index 7177248c415b..cccb7937d297 100644
--- a/libc/lib/CMakeLists.txt
+++ b/libc/lib/CMakeLists.txt
@@ -12,6 +12,9 @@ add_entrypoint_library(
# sys/mman.h entrypoints
mmap
munmap
+
+ # signal.h entrypoints
+ raise
)
add_entrypoint_library(
diff --git a/libc/spec/linux.td b/libc/spec/linux.td
index 2e773860d1eb..8903fdaf09b3 100644
--- a/libc/spec/linux.td
+++ b/libc/spec/linux.td
@@ -67,8 +67,53 @@ def Linux : StandardSpec<"Linux"> {
[] // 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,
];
}
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 3f9cdb0de9cb..8278e9da6734 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -179,10 +179,34 @@ def StdC : StandardSpec<"stdc"> {
[] // 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,
+ ],
+ [
+ FunctionSpec<"raise", RetValSpec<IntType>, [ArgSpec<IntType>]>,
+ ]
+ >;
+
let Headers = [
Errno,
Math,
String,
StdIO,
+ Signal,
];
}
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index b416e83934d6..0ff0a6ae70cd 100644
--- a/libc/src/CMakeLists.txt
+++ b/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)
diff --git a/libc/src/signal/CMakeLists.txt b/libc/src/signal/CMakeLists.txt
new file mode 100644
index 000000000000..d1a13bf1a3f4
--- /dev/null
+++ b/libc/src/signal/CMakeLists.txt
@@ -0,0 +1,4 @@
+
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/src/signal/linux/CMakeLists.txt b/libc/src/signal/linux/CMakeLists.txt
new file mode 100644
index 000000000000..a475a5853cd1
--- /dev/null
+++ b/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
+)
diff --git a/libc/src/signal/linux/raise.cpp b/libc/src/signal/linux/raise.cpp
new file mode 100644
index 000000000000..1f58636697ee
--- /dev/null
+++ b/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) {
+ __llvm_libc::Sigset sigset;
+ int got = __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
diff --git a/libc/src/signal/linux/signal.h b/libc/src/signal/linux/signal.h
new file mode 100644
index 000000000000..f70185ee39a7
--- /dev/null
+++ b/libc/src/signal/linux/signal.h
@@ -0,0 +1,49 @@
+//===----------------- 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 {
+
+// Using this internally defined type will make it easier in the future to port
+// to
diff erent architectures.
+struct Sigset {
+ sigset_t nativeSigset;
+
+ constexpr static Sigset fullset() { return {-1UL}; }
+
+ operator sigset_t() const { return nativeSigset; }
+};
+
+constexpr static Sigset all = Sigset::fullset();
+
+static inline int block_all_signals(Sigset &set) {
+ sigset_t nativeSigset = all;
+ sigset_t oldSet = set;
+ return __llvm_libc::syscall(SYS_rt_sigprocmask, SIG_BLOCK, &nativeSigset,
+ &oldSet, sizeof(sigset_t));
+}
+
+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));
+}
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SIGNAL_LINUX_SIGNAL_H
diff --git a/libc/src/signal/raise.h b/libc/src/signal/raise.h
new file mode 100644
index 000000000000..9cc89cc3907d
--- /dev/null
+++ b/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
diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index daf0f1ce57ce..bc698a64fa7d 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -1,3 +1,4 @@
add_subdirectory(errno)
+add_subdirectory(signal)
add_subdirectory(string)
add_subdirectory(sys)
diff --git a/libc/test/src/signal/CMakeLists.txt b/libc/test/src/signal/CMakeLists.txt
new file mode 100644
index 000000000000..dd1cc3b8b5d3
--- /dev/null
+++ b/libc/test/src/signal/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_libc_testsuite(libc_signal_unittests)
+
+add_libc_unittest(
+ raise_test
+ SUITE
+ libc_signal_unittests
+ SRCS
+ raise_test.cpp
+ DEPENDS
+ raise
+ signal_h
+)
diff --git a/libc/test/src/signal/raise_test.cpp b/libc/test/src/signal/raise_test.cpp
new file mode 100644
index 000000000000..8d48874c63c2
--- /dev/null
+++ b/libc/test/src/signal/raise_test.cpp
@@ -0,0 +1,17 @@
+//===----------------------- 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 "src/signal/raise.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(__llvm_libc::raise(SIGCONT), 0);
+}
More information about the libc-commits
mailing list