Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / components / nacl / loader / nonsfi / irt_thread.cc
blob3351bdc48b1dbbfee29eb063a668f6f1c7e102b6
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <errno.h>
6 #include <pthread.h>
7 #include <stdlib.h>
9 #include "base/macros.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "components/nacl/loader/nonsfi/irt_interfaces.h"
13 namespace nacl {
14 namespace nonsfi {
15 namespace {
17 // We heuristically chose 1M for the stack size per thread.
18 const int kStackSize = 1024 * 1024;
20 // For RAII of pthread_attr_t.
21 class ScopedPthreadAttrPtr {
22 public:
23 ScopedPthreadAttrPtr(pthread_attr_t* attr) : attr_(attr) {
25 ~ScopedPthreadAttrPtr() {
26 pthread_attr_destroy(attr_);
29 private:
30 pthread_attr_t* attr_;
33 struct ThreadContext {
34 void (*start_func)();
35 void* thread_ptr;
38 // A thread local pointer to support nacl_irt_tls.
39 // This should be initialized at the beginning of ThreadMain, which is a thin
40 // wrapper of a user function called on a newly created thread, and may be
41 // reset via IrtTlsInit(). The pointer can be obtained via IrtTlsGet().
42 __thread void* g_thread_ptr;
44 void* ThreadMain(void *arg) {
45 ::scoped_ptr<ThreadContext> context(static_cast<ThreadContext*>(arg));
46 g_thread_ptr = context->thread_ptr;
48 // Release the memory of context before running start_func.
49 void (*start_func)() = context->start_func;
50 context.reset();
52 start_func();
53 abort();
56 int IrtThreadCreate(void (*start_func)(), void* stack, void* thread_ptr) {
57 pthread_attr_t attr;
58 int error = pthread_attr_init(&attr);
59 if (error != 0)
60 return error;
61 ScopedPthreadAttrPtr scoped_attr_ptr(&attr);
63 // Note: Currently we ignore the argument stack.
64 error = pthread_attr_setstacksize(&attr, kStackSize);
65 if (error != 0)
66 return error;
68 error = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
69 if (error != 0)
70 return error;
72 ::scoped_ptr<ThreadContext> context(new ThreadContext);
73 context->start_func = start_func;
74 context->thread_ptr = thread_ptr;
76 pthread_t tid;
77 error = pthread_create(&tid, &attr, ThreadMain, context.get());
78 if (error != 0)
79 return error;
81 // The ownership of the context is taken by the created thread. So, here we
82 // just manually release it.
83 ignore_result(context.release());
84 return 0;
87 void IrtThreadExit(int32_t* stack_flag) {
88 // As we actually don't use stack given to thread_create, it means that the
89 // memory can be released whenever.
90 if (stack_flag)
91 *stack_flag = 0;
92 pthread_exit(NULL);
95 int IrtThreadNice(const int nice) {
96 // TODO(https://code.google.com/p/nativeclient/issues/detail?id=3734):
97 // Implement this method.
98 // Note that this is just a hint, so here we just return success without
99 // do anything.
100 return 0;
103 int IrtTlsInit(void* thread_ptr) {
104 g_thread_ptr = thread_ptr;
105 return 0;
108 void* IrtTlsGet() {
109 return g_thread_ptr;
112 } // namespace
114 const nacl_irt_thread kIrtThread = {
115 IrtThreadCreate,
116 IrtThreadExit,
117 IrtThreadNice,
120 const nacl_irt_tls kIrtTls = {
121 IrtTlsInit,
122 IrtTlsGet,
125 } // namespace nonsfi
126 } // namespace nacl