Use MADV_DONTNEED for alternate signal stack.

It seems MADV_FREE still counts toward PSS.

Also add a few checks before the `madvise()` call.

Test: testrunner.py --target --64 --optimizing
Bug: 38383823
Bug: 213757852
Change-Id: I8659f8f0490004eb5caba63d0c913931597393b9
diff --git a/runtime/thread_android.cc b/runtime/thread_android.cc
index 9b58c95..e8d01cc 100644
--- a/runtime/thread_android.cc
+++ b/runtime/thread_android.cc
@@ -17,6 +17,8 @@
 #include <signal.h>
 #include <sys/mman.h>
 
+#include "base/globals.h"
+#include "base/bit_utils.h"
 #include "thread.h"
 
 namespace art {
@@ -33,10 +35,16 @@
   stack_t old_ss;
   int result = sigaltstack(nullptr, &old_ss);
   CHECK_EQ(result, 0);
-  // Note: We're testing and benchmarking ART on devices with old kernels
-  // which may not support `MADV_FREE`, so we do not check the result.
-  // It should succeed on devices with Android 12+.
-  madvise(old_ss.ss_sp, old_ss.ss_size, MADV_FREE);
+  // Only call `madvise()` on enabled page-aligned alternate signal stack. Processes can
+  // create different arbitrary alternate signal stacks and we do not want to erroneously
+  // `madvise()` away pages that may hold data other than the alternate signal stack.
+  if ((old_ss.ss_flags & SS_DISABLE) == 0 &&
+      IsAligned<kPageSize>(old_ss.ss_sp) &&
+      IsAligned<kPageSize>(old_ss.ss_size)) {
+    CHECK_EQ(old_ss.ss_flags & SS_ONSTACK, 0);
+    result = madvise(old_ss.ss_sp, old_ss.ss_size, MADV_DONTNEED);
+    CHECK_EQ(result, 0);
+  }
 }
 
 }  // namespace art