OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include <errno.h> | |
6 #include <pthread.h> | |
7 #include <stdlib.h> | |
8 | |
9 #include "base/macros.h" | |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "components/nacl/loader/nonsfi/irt_interfaces.h" | |
12 | |
13 namespace nacl { | |
14 namespace nonsfi { | |
15 namespace { | |
16 | |
17 // We heuristically chose 1M for the stack size per thread. | |
18 const int kStackSize = 1024 * 1024; | |
19 | |
20 // For RAII of pthread_attr_t. | |
21 class ScopedPthreadAttrPtr { | |
22 public: | |
23 ScopedPthreadAttrPtr(pthread_attr_t* attr) : attr_(attr) { | |
24 } | |
25 ~ScopedPthreadAttrPtr() { | |
26 pthread_attr_destroy(attr_); | |
27 } | |
28 | |
29 private: | |
30 pthread_attr_t* attr_; | |
31 }; | |
32 | |
33 struct ThreadContext { | |
34 void (*start_func)(); | |
35 void* thread_ptr; | |
36 }; | |
37 | |
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; | |
43 | |
44 void* ThreadMain(void *arg) { | |
45 ::scoped_ptr<ThreadContext> context(static_cast<ThreadContext*>(arg)); | |
46 g_thread_ptr = context->thread_ptr; | |
47 | |
48 // Release the memory of context before running start_func. | |
49 void (*start_func)() = context->start_func; | |
50 context.reset(); | |
51 | |
52 start_func(); | |
53 abort(); | |
54 } | |
55 | |
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); | |
62 | |
63 // Note: Currently we ignore the argument stack. | |
64 error = pthread_attr_setstacksize(&attr, kStackSize); | |
65 if (error != 0) | |
66 return error; | |
67 | |
68 error = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | |
69 if (error != 0) | |
70 return error; | |
71 | |
72 ::scoped_ptr<ThreadContext> context(new ThreadContext); | |
73 context->start_func = start_func; | |
74 context->thread_ptr = thread_ptr; | |
75 | |
76 pthread_t tid; | |
77 error = pthread_create(&tid, &attr, ThreadMain, context.get()); | |
78 if (error != 0) | |
79 return error; | |
80 | |
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; | |
85 } | |
86 | |
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); | |
93 } | |
94 | |
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. | |
Mark Seaborn
2014/01/16 19:04:40
Nit: "doing" (I don't mind whether you fix this, b
| |
100 return 0; | |
101 } | |
102 | |
103 int IrtTlsInit(void* thread_ptr) { | |
104 g_thread_ptr = thread_ptr; | |
105 return 0; | |
106 } | |
107 | |
108 void* IrtTlsGet() { | |
109 return g_thread_ptr; | |
110 } | |
111 | |
112 } // namespace | |
113 | |
114 const nacl_irt_thread kIrtThread = { | |
115 IrtThreadCreate, | |
116 IrtThreadExit, | |
117 IrtThreadNice, | |
118 }; | |
119 | |
120 const nacl_irt_tls kIrtTls = { | |
121 IrtTlsInit, | |
122 IrtTlsGet, | |
123 }; | |
124 | |
125 } // namespace nonsfi | |
126 } // namespace nacl | |
OLD | NEW |