[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