Make Thread::InitStackHwm work on Mac OS.
Change-Id: Id0170dbdff8112d8e48d41ab50a311076863151e
diff --git a/src/thread.cc b/src/thread.cc
index d7a9b98..75e0f3e 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -375,27 +375,22 @@
}
void Thread::InitStackHwm() {
-#if defined(__APPLE__)
- // Only needed to run code. Try implementing this with pthread_get_stacksize_np and pthread_get_stackaddr_np.
- UNIMPLEMENTED(WARNING);
-#else
- pthread_attr_t attributes;
- CHECK_PTHREAD_CALL(pthread_getattr_np, (pthread_self(), &attributes), __FUNCTION__);
-
- void* temp_stack_base;
- CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, &temp_stack_base, &stack_size_),
- __FUNCTION__);
- stack_begin_ = reinterpret_cast<byte*>(temp_stack_base);
-
- CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
+ void* stack_base;
+ size_t stack_size;
+ GetThreadStack(stack_base, stack_size);
// TODO: include this in the thread dumps; potentially useful in SIGQUIT output?
- VLOG(threads) << "Native stack is at " << temp_stack_base << " (" << PrettySize(stack_size_) << ")";
+ VLOG(threads) << StringPrintf("Native stack is at %p (%s)", stack_base, PrettySize(stack_size).c_str());
+
+ stack_begin_ = reinterpret_cast<byte*>(stack_base);
+ stack_size_ = stack_size;
if (stack_size_ <= kStackOverflowReservedBytes) {
LOG(FATAL) << "Attempt to attach a thread with a too-small stack (" << stack_size_ << " bytes)";
}
+ // TODO: move this into the Linux GetThreadStack implementation.
+#if !defined(__APPLE__)
// If we're the main thread, check whether we were run with an unlimited stack. In that case,
// glibc will have reported a 2GB stack for our 32-bit process, and our stack overflow detection
// will be broken because we'll die long before we get close to 2GB.
@@ -417,11 +412,12 @@
size_t old_stack_size = stack_size_;
stack_size_ = default_stack_size;
stack_begin_ += (old_stack_size - stack_size_);
- LOG(WARNING) << "Limiting unlimited stack (reported as " << PrettySize(old_stack_size) << ");"
+ LOG(WARNING) << "Limiting unlimited stack (reported as " << PrettySize(old_stack_size) << ")"
<< " to " << PrettySize(stack_size_)
<< " with base " << reinterpret_cast<void*>(stack_begin_);
}
}
+#endif
// Set stack_end_ to the bottom of the stack saving space of stack overflows
ResetDefaultStackEnd();
@@ -429,7 +425,6 @@
// Sanity check.
int stack_variable;
CHECK_GT(&stack_variable, reinterpret_cast<void*>(stack_end_));
-#endif
}
void Thread::Dump(std::ostream& os, bool full) const {
diff --git a/src/utils.cc b/src/utils.cc
index 67fda67..bfa0c4f 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -66,6 +66,27 @@
#endif
}
+void GetThreadStack(void*& stack_base, size_t& stack_size) {
+#if defined(__APPLE__)
+ stack_size = pthread_get_stacksize_np(pthread_self());
+ void* stack_addr = pthread_get_stackaddr_np(pthread_self());
+
+ // Check whether stack_addr is the base or end of the stack.
+ // (On Mac OS 10.7, it's the end.)
+ int stack_variable;
+ if (stack_addr > &stack_variable) {
+ stack_base = reinterpret_cast<byte*>(stack_addr) - stack_size;
+ } else {
+ stack_base = stack_addr;
+ }
+#else
+ pthread_attr_t attributes;
+ CHECK_PTHREAD_CALL(pthread_getattr_np, (pthread_self(), &attributes), __FUNCTION__);
+ CHECK_PTHREAD_CALL(pthread_attr_getstack, (&attributes, &stack_base, &stack_size), __FUNCTION__);
+ CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attributes), __FUNCTION__);
+#endif
+}
+
bool ReadFileToString(const std::string& file_name, std::string* result) {
UniquePtr<File> file(OS::OpenFile(file_name.c_str(), false));
if (file.get() == NULL) {
diff --git a/src/utils.h b/src/utils.h
index 994e9bc..8e19ced 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -266,6 +266,9 @@
// Returns the calling thread's tid. (The C libraries don't expose this.)
pid_t GetTid();
+// Returns details of the calling thread's stack.
+void GetThreadStack(void*& stack_base, size_t& stack_size);
+
// Reads data from "/proc/self/task/${tid}/stat".
void GetTaskStats(pid_t tid, int& utime, int& stime, int& task_cpu);