Add POSIX 2024 NSIG_MAX.

https://www.austingroupbugs.net/view.php?id=741

Change-Id: I89117528e1ed8ab0f922bfa394fab16003070eab
diff --git a/libc/include/bits/signal_types.h b/libc/include/bits/signal_types.h
index d98901c..41a697e 100644
--- a/libc/include/bits/signal_types.h
+++ b/libc/include/bits/signal_types.h
@@ -34,36 +34,72 @@
 #include <linux/signal.h>
 #include <sys/types.h>
 
-/* The arm and x86 kernel header files don't define _NSIG. */
+/**
+ * The highest kernel-supported signal number, plus one.
+ *
+ * In theory this is useful for declaring an array with an entry for each signal.
+ * In practice, that's less useful than it seems because of the real-time
+ * signals and the reserved signals,
+ * and the sig2str() and str2sig() functions cover the most common use case
+ * of translating between signal numbers and signal names.
+ *
+ * Note also that although sigset_t and sigset64_t are the same type on LP64,
+ * on ILP32 only sigset64_t is large enough to refer to the upper 32 signals.
+ * NSIG does _not_ tell you anything about what can be used with sigset_t.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
+#define NSIG 65
+/** A traditional alternative name for NSIG. */
+#define _NSIG 65
+
+/*
+ * We rewrite the kernel's _NSIG to _KERNEL__NSIG
+ * (because the kernel values are off by one from the userspace values),
+ * but the kernel <asm/signal.h> headers define SIGRTMAX in terms of
+ * _KERNEL__NSIG (or _NSIG, in the original kernel source),
+ * so we need to provide a definition here.
+ * (Ideally our uapi header rewriter would just hard-code _KERNEL__NSIG to 64.)
+ */
 #ifndef _KERNEL__NSIG
 #define _KERNEL__NSIG 64
 #endif
 
-/* Userspace's NSIG is the kernel's _NSIG + 1. */
-#define _NSIG (_KERNEL__NSIG + 1)
-#define NSIG _NSIG
-
 typedef int sig_atomic_t;
 
 typedef __sighandler_t sig_t; /* BSD compatibility. */
 typedef __sighandler_t sighandler_t; /* glibc compatibility. */
 
-/* sigset_t is already large enough on LP64, but LP32's sigset_t
- * is just `unsigned long`.
- */
 #if defined(__LP64__)
+/**
+ * The kernel LP64 sigset_t is large enough to support all signals;
+ * this typedef is just for source compatibility with code that uses
+ * real-time signals on ILP32.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
 typedef sigset_t sigset64_t;
 #else
-typedef struct { unsigned long __bits[_KERNEL__NSIG/(8*sizeof(long))]; } sigset64_t;
+/**
+ * The ILP32 sigset_t is only 32 bits, so we need a 64-bit sigset64_t
+ * and associated functions to be able to support the real-time signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
+typedef struct { unsigned long __bits[64/(8*sizeof(long))]; } sigset64_t;
 #endif
 
-/* The kernel's struct sigaction doesn't match the POSIX one. */
+/* The kernel's struct sigaction doesn't match the POSIX one,
+ * so we define struct sigaction ourselves. */
 
 #if defined(__LP64__)
 
-/* For 64-bit, that's the only problem, and we only need two structs
- * for source compatibility with 32-bit. */
-
 #define __SIGACTION_BODY \
   int sa_flags; \
   union { \
@@ -73,22 +109,49 @@
   sigset_t sa_mask; \
   void (*sa_restorer)(void); \
 
+/**
+ * Used with sigaction().
+ *
+ * On LP64, this supports all signals including real-time signals.
+ * On ILP32, this only supports the first 32 signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
 struct sigaction { __SIGACTION_BODY };
+/**
+ * Used with sigaction64().
+ *
+ * On LP64, a synonym for struct sigaction for source compatibility with ILP32.
+ * On ILP32, this is needed to support all signals including real-time signals
+ * because struct sigaction only supports the first 32 signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
 struct sigaction64 { __SIGACTION_BODY };
 
 #undef __SIGACTION_BODY
 
 #else
 
-/* For 32-bit, Android's ABIs used a too-small sigset_t that doesn't
- * support RT signals, so we need two different structs.
- */
-
-/* The arm32 kernel headers also pollute the namespace with these,
+/* The arm32 kernel headers pollute the namespace with these,
  * but our header scrubber doesn't know how to remove #defines. */
 #undef sa_handler
 #undef sa_sigaction
 
+/**
+ * Used with sigaction().
+ *
+ * On LP64, this supports all signals including real-time signals.
+ * On ILP32, this only supports the first 32 signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
 struct sigaction {
   union {
     sighandler_t sa_handler;
@@ -99,6 +162,17 @@
   void (*sa_restorer)(void);
 };
 
+/**
+ * Used with sigaction64().
+ *
+ * On LP64, a synonym for struct sigaction for source compatibility with ILP32.
+ * On ILP32, this is needed to support all signals including real-time signals
+ * because struct sigaction only supports the first 32 signals.
+ *
+ * See the
+ * (32-bit ABI bugs)[https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md#is-too-small-for-real_time-signals]
+ * documentation.
+ */
 struct sigaction64 {
   union {
     sighandler_t sa_handler;
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 5c0ef6d..3220415 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -96,6 +96,12 @@
 /** Maximum value of a ssize_t. */
 #define SSIZE_MAX LONG_MAX
 
+/**
+ * POSIX 2024's name for NSIG.
+ * See the NSIG documentation for an explanation and warnings.
+ */
+#define NSIG_MAX 65
+
 /** Maximum number of bytes in a multibyte character. */
 #define MB_LEN_MAX 4
 
diff --git a/tests/headers/posix/limits_h.c b/tests/headers/posix/limits_h.c
index 0ca80a5..0a3bc1c 100644
--- a/tests/headers/posix/limits_h.c
+++ b/tests/headers/posix/limits_h.c
@@ -58,6 +58,9 @@
 #if !defined(__BIONIC__)
   MACRO(MQ_PRIO_MAX);
 #endif
+#if defined(__BIONIC__)
+  MACRO(NSIG_MAX);
+#endif
 #if !defined(__BIONIC__) && !defined(__GLIBC__) && !defined(ANDROID_HOST_MUSL)
   MACRO(OPEN_MAX);
 #endif
diff --git a/tests/limits_test.cpp b/tests/limits_test.cpp
index bc13a3f..64d9a33 100644
--- a/tests/limits_test.cpp
+++ b/tests/limits_test.cpp
@@ -78,3 +78,11 @@
 #error ULLONG_MAX
 #endif
 }
+
+TEST(limits, highest_signal_plus_one) {
+#if defined(__BIONIC__)
+  ASSERT_EQ(65, NSIG_MAX);
+#endif
+  ASSERT_EQ(65, NSIG);
+  ASSERT_EQ(65, _NSIG);
+}