Merge "Improve a debug message to log a more useful namespace."
diff --git a/docs/status.md b/docs/status.md
index ef60ce2..20a1309 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -54,6 +54,7 @@
 New libc functions in U (API level 34):
   * `close_range` and `copy_file_range` (Linux-specific GNU extensions).
   * `memset_explicit` in <string.h> (C23 addition).
+  * `__freadahead` in <stdio_ext.h> (in musl but not glibc).
 
 New libc behavior in U (API level 34):
   * Support for `%b` and `%B` in the printf/wprintf family, `%b` in the
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index f7f4d31..6433b59 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -101,7 +101,7 @@
   }
 
   size_t offset = idx - inline_fds;
-  if (local_overflow->len < offset) {
+  if (local_overflow->len <= offset) {
     return nullptr;
   }
   return &local_overflow->entries[offset];
diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h
index 3aa183d..eda5919 100644
--- a/libc/include/stdio_ext.h
+++ b/libc/include/stdio_ext.h
@@ -96,13 +96,21 @@
 
 /**
  * [__fpending(3)](http://man7.org/linux/man-pages/man3/__fpending.3.html) returns the number of
- * bytes in the output buffer.
+ * bytes in the output buffer. See __freadahead() for the input buffer.
  *
  * Available since API level 23.
  */
 size_t __fpending(FILE* __fp) __INTRODUCED_IN(23);
 
 /**
+ * __freadahead(3) returns the number of bytes in the input buffer.
+ * See __fpending() for the output buffer.
+ *
+ * Available since API level 34.
+ */
+size_t __freadahead(FILE* __fp) __INTRODUCED_IN(34);
+
+/**
  * [_flushlbf(3)](http://man7.org/linux/man-pages/man3/_flushlbf.3.html) flushes all
  * line-buffered streams.
  *
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 6ef0c12..9e865a3 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -168,8 +168,13 @@
  * PID file descriptor.
  *
  * Returns the number of bytes advised on success, and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 31. Its sibling process_mrelease() does not have a
+ * libc wrapper and should be called using syscall() instead. Given the lack of
+ * widespread applicability of this system call and the absence of wrappers in
+ * other libcs, it was probably a mistake to have added this wrapper to bionic.
  */
-ssize_t process_madvise(int __pid_fd, const struct iovec* __iov, size_t __count, int __advice, unsigned __flags);
+ssize_t process_madvise(int __pid_fd, const struct iovec* __iov, size_t __count, int __advice, unsigned __flags) __INTRODUCED_IN(31);
 
 #if defined(__USE_GNU)
 
diff --git a/libc/kernel/tools/generate_uapi_headers.sh b/libc/kernel/tools/generate_uapi_headers.sh
index 7e49cde..12f60e5 100755
--- a/libc/kernel/tools/generate_uapi_headers.sh
+++ b/libc/kernel/tools/generate_uapi_headers.sh
@@ -43,7 +43,7 @@
 ANDROID_KERNEL_BRANCH="android-mainline"
 KERNEL_DIR=""
 KERNEL_DOWNLOAD=0
-ARCH_LIST=("arm" "arm64" "x86")
+ARCH_LIST=("arm" "arm64" "riscv" "x86")
 ANDROID_KERNEL_DIR="external/kernel-headers/original"
 SKIP_GENERATION=0
 VERIFY_HEADERS_ONLY=0
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 0f41878..e8d03b9 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1578,6 +1578,7 @@
 
 LIBC_U { # introduced=UpsideDownCake
   global:
+    __freadahead;
     close_range;
     copy_file_range;
     memset_explicit;
diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp
index 945813e..99a8af7 100644
--- a/libc/stdio/stdio_ext.cpp
+++ b/libc/stdio/stdio_ext.cpp
@@ -67,6 +67,12 @@
   return fp->_p - fp->_bf._base;
 }
 
+size_t __freadahead(FILE* fp) {
+  // Normally _r is the amount of input already available.
+  // When there's ungetc() data, _r counts that and _ur is the previous _r.
+  return fp->_r + (HASUB(fp) ? fp->_ur : 0);
+}
+
 void _flushlbf() {
   // If we flush all streams, we know we've flushed all the line-buffered streams.
   fflush(nullptr);
diff --git a/tests/stack_protector_test_helper.cpp b/tests/stack_protector_test_helper.cpp
index fd90b93..eddd940 100644
--- a/tests/stack_protector_test_helper.cpp
+++ b/tests/stack_protector_test_helper.cpp
@@ -19,7 +19,8 @@
   // We can't use memset here because it's fortified, and we want to test
   // the line of defense *after* that.
   // Without volatile, the generic x86/x86-64 targets don't write to the stack.
-  volatile char* p;
-  p = reinterpret_cast<volatile char*>(&p + 1);
-  *p = '\0';
+  // We can't make a constant change, since the existing byte might already have
+  // had that value.
+  volatile char* p = reinterpret_cast<volatile char*>(&p + 1);
+  *p = ~*p;
 }
diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp
index fce600a..dce1a66 100644
--- a/tests/stdio_ext_test.cpp
+++ b/tests/stdio_ext_test.cpp
@@ -78,6 +78,24 @@
   fclose(fp);
 }
 
+TEST(stdio_ext, __freadahead) {
+#if defined(__GLIBC__)
+  GTEST_SKIP() << "glibc doesn't have __freadahead";
+#else
+  FILE* fp = tmpfile();
+  ASSERT_NE(EOF, fputs("hello", fp));
+  rewind(fp);
+
+  ASSERT_EQ('h', fgetc(fp));
+  ASSERT_EQ(4u, __freadahead(fp));
+
+  ASSERT_EQ('H', ungetc('H', fp));
+  ASSERT_EQ(5u, __freadahead(fp));
+
+  fclose(fp);
+#endif
+}
+
 TEST(stdio_ext, __fpurge) {
   FILE* fp = tmpfile();
 
diff --git a/tests/sys_sysinfo_test.cpp b/tests/sys_sysinfo_test.cpp
index cca2f44..69656ad 100644
--- a/tests/sys_sysinfo_test.cpp
+++ b/tests/sys_sysinfo_test.cpp
@@ -43,7 +43,7 @@
   memset(&si, 0, sizeof(si));
   ASSERT_EQ(0, sysinfo(&si));
 
-  ASSERT_GT(si.uptime, 10);  // You're not running CTS within 10s of booting!
+  ASSERT_GT(static_cast<long>(si.uptime), 10);  // You're not running CTS within 10s of booting!
   ASSERT_GT(uint64_t(si.totalram) * si.mem_unit, uint64_t(512 * 1024 * 1024));
   ASSERT_GE(si.totalram, si.freeram);
   ASSERT_GE(si.totalswap, si.freeswap);