Index: components/nacl/loader/nonsfi/irt_thread.cc |
diff --git a/components/nacl/loader/nonsfi/irt_thread.cc b/components/nacl/loader/nonsfi/irt_thread.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3351bdc48b1dbbfee29eb063a668f6f1c7e102b6 |
--- /dev/null |
+++ b/components/nacl/loader/nonsfi/irt_thread.cc |
@@ -0,0 +1,126 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <errno.h> |
+#include <pthread.h> |
+#include <stdlib.h> |
+ |
+#include "base/macros.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "components/nacl/loader/nonsfi/irt_interfaces.h" |
+ |
+namespace nacl { |
+namespace nonsfi { |
+namespace { |
+ |
+// We heuristically chose 1M for the stack size per thread. |
+const int kStackSize = 1024 * 1024; |
+ |
+// For RAII of pthread_attr_t. |
+class ScopedPthreadAttrPtr { |
+ public: |
+ ScopedPthreadAttrPtr(pthread_attr_t* attr) : attr_(attr) { |
+ } |
+ ~ScopedPthreadAttrPtr() { |
+ pthread_attr_destroy(attr_); |
+ } |
+ |
+ private: |
+ pthread_attr_t* attr_; |
+}; |
+ |
+struct ThreadContext { |
+ void (*start_func)(); |
+ void* thread_ptr; |
+}; |
+ |
+// A thread local pointer to support nacl_irt_tls. |
+// This should be initialized at the beginning of ThreadMain, which is a thin |
+// wrapper of a user function called on a newly created thread, and may be |
+// reset via IrtTlsInit(). The pointer can be obtained via IrtTlsGet(). |
+__thread void* g_thread_ptr; |
+ |
+void* ThreadMain(void *arg) { |
+ ::scoped_ptr<ThreadContext> context(static_cast<ThreadContext*>(arg)); |
+ g_thread_ptr = context->thread_ptr; |
+ |
+ // Release the memory of context before running start_func. |
+ void (*start_func)() = context->start_func; |
+ context.reset(); |
+ |
+ start_func(); |
+ abort(); |
+} |
+ |
+int IrtThreadCreate(void (*start_func)(), void* stack, void* thread_ptr) { |
+ pthread_attr_t attr; |
+ int error = pthread_attr_init(&attr); |
+ if (error != 0) |
+ return error; |
+ ScopedPthreadAttrPtr scoped_attr_ptr(&attr); |
+ |
+ // Note: Currently we ignore the argument stack. |
+ error = pthread_attr_setstacksize(&attr, kStackSize); |
+ if (error != 0) |
+ return error; |
+ |
+ error = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
+ if (error != 0) |
+ return error; |
+ |
+ ::scoped_ptr<ThreadContext> context(new ThreadContext); |
+ context->start_func = start_func; |
+ context->thread_ptr = thread_ptr; |
+ |
+ pthread_t tid; |
+ error = pthread_create(&tid, &attr, ThreadMain, context.get()); |
+ if (error != 0) |
+ return error; |
+ |
+ // The ownership of the context is taken by the created thread. So, here we |
+ // just manually release it. |
+ ignore_result(context.release()); |
+ return 0; |
+} |
+ |
+void IrtThreadExit(int32_t* stack_flag) { |
+ // As we actually don't use stack given to thread_create, it means that the |
+ // memory can be released whenever. |
+ if (stack_flag) |
+ *stack_flag = 0; |
+ pthread_exit(NULL); |
+} |
+ |
+int IrtThreadNice(const int nice) { |
+ // TODO(https://code.google.com/p/nativeclient/issues/detail?id=3734): |
+ // Implement this method. |
+ // Note that this is just a hint, so here we just return success without |
+ // do anything. |
Mark Seaborn
2014/01/16 19:04:40
Nit: "doing" (I don't mind whether you fix this, b
|
+ return 0; |
+} |
+ |
+int IrtTlsInit(void* thread_ptr) { |
+ g_thread_ptr = thread_ptr; |
+ return 0; |
+} |
+ |
+void* IrtTlsGet() { |
+ return g_thread_ptr; |
+} |
+ |
+} // namespace |
+ |
+const nacl_irt_thread kIrtThread = { |
+ IrtThreadCreate, |
+ IrtThreadExit, |
+ IrtThreadNice, |
+}; |
+ |
+const nacl_irt_tls kIrtTls = { |
+ IrtTlsInit, |
+ IrtTlsGet, |
+}; |
+ |
+} // namespace nonsfi |
+} // namespace nacl |