1 : /*
2 : * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : #include "native_client/src/trusted/threading/nacl_thread_interface.h"
8 :
9 : #include "native_client/src/include/nacl_compiler_annotations.h"
10 :
11 : #include "native_client/src/shared/platform/nacl_check.h"
12 : #include "native_client/src/shared/platform/nacl_log.h"
13 : #include "native_client/src/shared/platform/nacl_threads.h"
14 : #include "native_client/src/trusted/nacl_base/nacl_refcount.h"
15 :
16 546 : void WINAPI NaClThreadInterfaceStart(void *data) {
17 546 : struct NaClThreadInterface *tif =
18 : (struct NaClThreadInterface *) data;
19 546 : void *thread_return;
20 :
21 546 : NaClLog(4,
22 : ("Entered NaClThreadInterfaceStart: thread object 0x%"NACL_PRIxPTR
23 : " starting.\n"),
24 : (uintptr_t) tif); /* NaClThreadId() implicitly printed */
25 546 : (*NACL_VTBL(NaClThreadInterface, tif)->LaunchCallback)(tif);
26 546 : thread_return = (*tif->fn_ptr)(tif);
27 546 : NaClLog(4,
28 : ("NaClThreadInterfaceStart: thread object 0x%"NACL_PRIxPTR
29 : " returned 0x%"NACL_PRIxPTR".\n"),
30 : (uintptr_t) tif,
31 : (uintptr_t) thread_return); /* NaClThreadId() implicitly printed */
32 546 : (*NACL_VTBL(NaClThreadInterface, tif)->Exit)(tif, thread_return);
33 546 : NaClLog(LOG_FATAL,
34 : "NaClThreadInterface: Exit member function did not exit thread\n");
35 546 : }
36 :
37 : int NaClThreadInterfaceCtor_protected(
38 546 : struct NaClThreadInterface *self,
39 546 : NaClThreadIfFactoryFunction factory,
40 546 : void *factory_data,
41 546 : NaClThreadIfStartFunction fn_ptr,
42 546 : void *thread_data,
43 546 : size_t thread_stack_size) {
44 :
45 546 : NaClLog(3, "Entered NaClThreadInterfaceThreadPlacementFactory\n");
46 546 : if (!NaClRefCountCtor((struct NaClRefCount *) self)) {
47 0 : NaClLog(3,
48 : "NaClThreadInterfaceThreadPlacementFactory,"
49 : " NaClRefCountCtor base class ctor failed\n");
50 0 : return 0;
51 : }
52 :
53 546 : self->factory = factory;
54 546 : self->factory_data = factory_data;
55 546 : self->thread_stack_size = thread_stack_size;
56 546 : self->fn_ptr = fn_ptr;
57 546 : self->thread_data = thread_data;
58 546 : self->thread_started = 0;
59 546 : NACL_VTBL(NaClRefCount, self) =
60 : (struct NaClRefCountVtbl const *) &kNaClThreadInterfaceVtbl;
61 546 : NaClLog(3,
62 : "Leaving NaClThreadInterfaceThreadPlacementFactory, returning 1\n");
63 546 : return 1;
64 546 : }
65 :
66 : int NaClThreadInterfaceThreadFactory(
67 21 : void *factory_data,
68 21 : NaClThreadIfStartFunction fn_ptr,
69 21 : void *thread_data,
70 21 : size_t thread_stack_size,
71 21 : struct NaClThreadInterface **out_new_thread) {
72 21 : struct NaClThreadInterface *new_thread;
73 21 : int rv;
74 :
75 21 : NaClLog(3, "Entered NaClThreadInterfaceThreadFactory\n");
76 21 : new_thread = malloc(sizeof *new_thread);
77 21 : if (NULL == new_thread) {
78 0 : NaClLog(3, "NaClThreadInterfaceThreadFactory: no memory!\n");
79 0 : return 0;
80 : }
81 : if (0 != (rv =
82 21 : NaClThreadInterfaceCtor_protected(
83 : new_thread,
84 : NaClThreadInterfaceThreadFactory,
85 : factory_data,
86 : fn_ptr,
87 : thread_data,
88 : thread_stack_size))) {
89 21 : *out_new_thread = new_thread;
90 21 : NaClLog(3,
91 : "NaClThreadInterfaceThreadFactory: new thread object"
92 : " 0x%"NACL_PRIxPTR" (not started)\n",
93 : (uintptr_t) new_thread);
94 21 : new_thread = NULL;
95 21 : }
96 21 : free(new_thread);
97 21 : NaClLog(3,
98 : "Leaving NaClThreadInterfaceThreadFactory, returning %d\n",
99 : rv);
100 21 : return rv;
101 21 : }
102 :
103 3 : void NaClThreadInterfaceDtor(struct NaClRefCount *vself) {
104 3 : struct NaClThreadInterface *self =
105 : (struct NaClThreadInterface *) vself;
106 9 : CHECK(self->thread_started == 0);
107 3 : self->fn_ptr = NULL;
108 3 : self->thread_data = NULL;
109 3 : NACL_VTBL(NaClRefCount, self) = &kNaClRefCountVtbl;
110 3 : (*NACL_VTBL(NaClRefCount, self)->Dtor)(vself);
111 3 : }
112 :
113 546 : int NaClThreadInterfaceStartThread(struct NaClThreadInterface *self) {
114 546 : int rv;
115 :
116 546 : NaClLog(3,
117 : "Entered NaClThreadInterfaceStartThread: self 0x%"NACL_PRIxPTR"\n",
118 : (uintptr_t) self);
119 1638 : CHECK(self->thread_started == 0);
120 :
121 546 : rv = NaClThreadCtor(&self->thread,
122 : NaClThreadInterfaceStart,
123 : self,
124 : self->thread_stack_size);
125 546 : if (rv) {
126 546 : self->thread_started = 1;
127 546 : }
128 546 : NaClLog(3, "Leaving NaClThreadInterfaceStartThread, rv=%d\n", rv);
129 546 : return rv;
130 : }
131 :
132 : /*
133 : * Default LaunchCallback does nothing. We could have made this "pure
134 : * virtual" by doing NaClLog(LOG_FATAL, ...) in the body (at least
135 : * detected at runtime).
136 : */
137 21 : void NaClThreadInterfaceLaunchCallback(struct NaClThreadInterface *self) {
138 21 : NaClLog(3,
139 : "NaClThreadInterfaceLaunchCallback: thread 0x%"NACL_PRIxPTR"\n",
140 : (uintptr_t) self);
141 21 : }
142 :
143 3 : void NaClThreadInterfaceExit(struct NaClThreadInterface *self,
144 3 : void *exit_code) {
145 6 : UNREFERENCED_PARAMETER(exit_code);
146 :
147 3 : NaClLog(3,
148 : "NaClThreadInterfaceExit: thread 0x%"NACL_PRIxPTR"\n",
149 : (uintptr_t) self);
150 3 : self->thread_started = 0; /* on way out */
151 3 : NaClRefCountUnref((struct NaClRefCount *) self);
152 3 : NaClThreadExit();
153 3 : }
154 :
155 : struct NaClThreadInterfaceVtbl const kNaClThreadInterfaceVtbl = {
156 : {
157 : NaClThreadInterfaceDtor,
158 : },
159 : NaClThreadInterfaceStartThread,
160 : NaClThreadInterfaceLaunchCallback,
161 : NaClThreadInterfaceExit,
162 : };
163 :
164 : int NaClThreadInterfaceConstructAndStartThread(
165 546 : NaClThreadIfFactoryFunction factory_fn,
166 546 : void *factory_data,
167 546 : NaClThreadIfStartFunction thread_fn_ptr,
168 546 : void *thread_data,
169 546 : size_t thread_stack_size,
170 546 : struct NaClThreadInterface **out_new_thread) {
171 546 : struct NaClThreadInterface *new_thread;
172 :
173 546 : NaClLog(3,
174 : "NaClThreadInterfaceConstructAndStartThread: invoking factory"
175 : " function 0x%"NACL_PRIxPTR", factory data 0x%"NACL_PRIxPTR"\n",
176 : (uintptr_t) factory_fn, (uintptr_t) factory_data);
177 546 : if (!(*factory_fn)(factory_data,
178 : thread_fn_ptr,
179 : thread_data,
180 : thread_stack_size,
181 : &new_thread)) {
182 0 : NaClLog(3,
183 : ("NaClThreadInterfaceConstructAndStartThread:"
184 : " factory 0x%"NACL_PRIxPTR" failed to produce!\n"),
185 : (uintptr_t) factory_fn);
186 0 : new_thread = NULL;
187 0 : goto abort;
188 : }
189 546 : NaClLog(3,
190 : "NaClThreadInterfaceConstructAndStartThread: StartThread vfn\n");
191 546 : if (!(*NACL_VTBL(NaClThreadInterface, new_thread)->StartThread)(
192 : new_thread)) {
193 0 : NaClLog(3,
194 : ("NaClThreadInterfaceConstructAndStartThread:"
195 : " factory 0x%"NACL_PRIxPTR" produced a thread 0x%"NACL_PRIxPTR
196 : " that won't start!\n"),
197 : (uintptr_t) factory_fn,
198 : (uintptr_t) new_thread);
199 0 : NaClRefCountUnref((struct NaClRefCount *) new_thread);
200 0 : new_thread = NULL;
201 0 : goto abort;
202 : }
203 546 : NaClLog(4,
204 : ("NaClThreadInterfaceConstructAndStartThread: thread 0x%"NACL_PRIxPTR
205 : " started\n"),
206 : (uintptr_t) new_thread);
207 : abort:
208 546 : *out_new_thread = new_thread;
209 546 : return new_thread != NULL;
210 : }
|