1 /*
2 * Copyright (C) 2011-2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "rsdCore.h"
18 #include "rsdAllocation.h"
19 #include "rsdBcc.h"
20 #include "rsdGL.h"
21 #include "rsdPath.h"
22 #include "rsdProgramStore.h"
23 #include "rsdProgramRaster.h"
24 #include "rsdProgramVertex.h"
25 #include "rsdProgramFragment.h"
26 #include "rsdMesh.h"
27 #include "rsdSampler.h"
28 #include "rsdFrameBuffer.h"
29
30 #include <malloc.h>
31 #include "rsContext.h"
32
33 #include <sys/types.h>
34 #include <sys/resource.h>
35 #include <sched.h>
36 #include <cutils/properties.h>
37 #include <sys/syscall.h>
38 #include <string.h>
39 #include <bcc/bcc.h>
40
41 using namespace android;
42 using namespace android::renderscript;
43
44 static void Shutdown(Context *rsc);
45 static void SetPriority(const Context *rsc, int32_t priority);
46
47 static RsdHalFunctions FunctionTable = {
48 rsdGLInit,
49 rsdGLShutdown,
50 rsdGLSetSurface,
51 rsdGLSwap,
52
53 Shutdown,
54 NULL,
55 SetPriority,
56 {
57 rsdScriptInit,
58 rsdScriptInvokeFunction,
59 rsdScriptInvokeRoot,
60 rsdScriptInvokeForEach,
61 rsdScriptInvokeInit,
62 rsdScriptInvokeFreeChildren,
63 rsdScriptSetGlobalVar,
64 rsdScriptSetGlobalVarWithElemDims,
65 rsdScriptSetGlobalBind,
66 rsdScriptSetGlobalObj,
67 rsdScriptDestroy
68 },
69
70 {
71 rsdAllocationInit,
72 rsdAllocationDestroy,
73 rsdAllocationResize,
74 rsdAllocationSyncAll,
75 rsdAllocationMarkDirty,
76 rsdAllocationInitSurfaceTexture,
77 rsdAllocationSetSurfaceTexture,
78 rsdAllocationIoSend,
79 rsdAllocationIoReceive,
80 rsdAllocationData1D,
81 rsdAllocationData2D,
82 rsdAllocationData3D,
83 rsdAllocationData1D_alloc,
84 rsdAllocationData2D_alloc,
85 rsdAllocationData3D_alloc,
86 rsdAllocationElementData1D,
87 rsdAllocationElementData2D
88 },
89
90
91 {
92 rsdProgramStoreInit,
93 rsdProgramStoreSetActive,
94 rsdProgramStoreDestroy
95 },
96
97 {
98 rsdProgramRasterInit,
99 rsdProgramRasterSetActive,
100 rsdProgramRasterDestroy
101 },
102
103 {
104 rsdProgramVertexInit,
105 rsdProgramVertexSetActive,
106 rsdProgramVertexDestroy
107 },
108
109 {
110 rsdProgramFragmentInit,
111 rsdProgramFragmentSetActive,
112 rsdProgramFragmentDestroy
113 },
114
115 {
116 rsdMeshInit,
117 rsdMeshDraw,
118 rsdMeshDestroy
119 },
120
121 {
122 rsdPathInitStatic,
123 rsdPathInitDynamic,
124 rsdPathDraw,
125 rsdPathDestroy
126 },
127
128 {
129 rsdSamplerInit,
130 rsdSamplerDestroy
131 },
132
133 {
134 rsdFrameBufferInit,
135 rsdFrameBufferSetActive,
136 rsdFrameBufferDestroy
137 },
138
139 };
140
141 pthread_key_t rsdgThreadTLSKey = 0;
142 uint32_t rsdgThreadTLSKeyCount = 0;
143 pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER;
144
145
HelperThreadProc(void * vrsc)146 static void * HelperThreadProc(void *vrsc) {
147 Context *rsc = static_cast<Context *>(vrsc);
148 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
149
150
151 uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount);
152
153 //ALOGV("RS helperThread starting %p idx=%i", rsc, idx);
154
155 dc->mWorkers.mLaunchSignals[idx].init();
156 dc->mWorkers.mNativeThreadId[idx] = gettid();
157
158 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
159 if (status) {
160 ALOGE("pthread_setspecific %i", status);
161 }
162
163 #if 0
164 typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t;
165 cpu_set_t cpuset;
166 memset(&cpuset, 0, sizeof(cpuset));
167 cpuset.bits[idx / 64] |= 1ULL << (idx % 64);
168 int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx],
169 sizeof(cpuset), &cpuset);
170 ALOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret));
171 #endif
172
173 while (!dc->mExit) {
174 dc->mWorkers.mLaunchSignals[idx].wait();
175 if (dc->mWorkers.mLaunchCallback) {
176 dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx);
177 }
178 android_atomic_dec(&dc->mWorkers.mRunningCount);
179 dc->mWorkers.mCompleteSignal.set();
180 }
181
182 //ALOGV("RS helperThread exited %p idx=%i", rsc, idx);
183 return NULL;
184 }
185
rsdLaunchThreads(Context * rsc,WorkerCallback_t cbk,void * data)186 void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) {
187 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
188
189 dc->mWorkers.mLaunchData = data;
190 dc->mWorkers.mLaunchCallback = cbk;
191 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
192 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
193 dc->mWorkers.mLaunchSignals[ct].set();
194 }
195 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
196 dc->mWorkers.mCompleteSignal.wait();
197 }
198 }
199
rsdHalInit(Context * rsc,uint32_t version_major,uint32_t version_minor)200 bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) {
201 rsc->mHal.funcs = FunctionTable;
202
203 RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal));
204 if (!dc) {
205 ALOGE("Calloc for driver hal failed.");
206 return false;
207 }
208 rsc->mHal.drv = dc;
209
210 pthread_mutex_lock(&rsdgInitMutex);
211 if (!rsdgThreadTLSKeyCount) {
212 int status = pthread_key_create(&rsdgThreadTLSKey, NULL);
213 if (status) {
214 ALOGE("Failed to init thread tls key.");
215 pthread_mutex_unlock(&rsdgInitMutex);
216 return false;
217 }
218 }
219 rsdgThreadTLSKeyCount++;
220 pthread_mutex_unlock(&rsdgInitMutex);
221
222 dc->mTlsStruct.mContext = rsc;
223 dc->mTlsStruct.mScript = NULL;
224 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
225 if (status) {
226 ALOGE("pthread_setspecific %i", status);
227 }
228
229
230 int cpu = sysconf(_SC_NPROCESSORS_ONLN);
231 if(rsc->props.mDebugMaxThreads && (cpu > (int)rsc->props.mDebugMaxThreads)) {
232 cpu = rsc->props.mDebugMaxThreads;
233 }
234 if (cpu < 2) {
235 cpu = 0;
236 }
237 ALOGV("%p Launching thread(s), CPUs %i", rsc, cpu);
238
239 dc->mWorkers.mCount = (uint32_t)cpu;
240 dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t));
241 dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t));
242 dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount];
243 dc->mWorkers.mLaunchCallback = NULL;
244
245 dc->mWorkers.mCompleteSignal.init();
246
247 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
248 android_atomic_release_store(0, &dc->mWorkers.mLaunchCount);
249
250 pthread_attr_t threadAttr;
251 status = pthread_attr_init(&threadAttr);
252 if (status) {
253 ALOGE("Failed to init thread attribute.");
254 return false;
255 }
256
257 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
258 status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc);
259 if (status) {
260 dc->mWorkers.mCount = ct;
261 ALOGE("Created fewer than expected number of RS threads.");
262 break;
263 }
264 }
265 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
266 usleep(100);
267 }
268
269 pthread_attr_destroy(&threadAttr);
270 return true;
271 }
272
273
SetPriority(const Context * rsc,int32_t priority)274 void SetPriority(const Context *rsc, int32_t priority) {
275 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
276 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
277 setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority);
278 }
279 if (dc->mHasGraphics) {
280 rsdGLSetPriority(rsc, priority);
281 }
282 }
283
Shutdown(Context * rsc)284 void Shutdown(Context *rsc) {
285 RsdHal *dc = (RsdHal *)rsc->mHal.drv;
286
287 dc->mExit = true;
288 dc->mWorkers.mLaunchData = NULL;
289 dc->mWorkers.mLaunchCallback = NULL;
290 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
291 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
292 dc->mWorkers.mLaunchSignals[ct].set();
293 }
294 int status;
295 void *res;
296 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
297 status = pthread_join(dc->mWorkers.mThreadId[ct], &res);
298 }
299 rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0);
300
301 // Global structure cleanup.
302 pthread_mutex_lock(&rsdgInitMutex);
303 --rsdgThreadTLSKeyCount;
304 if (!rsdgThreadTLSKeyCount) {
305 pthread_key_delete(rsdgThreadTLSKey);
306 }
307 pthread_mutex_unlock(&rsdgInitMutex);
308
309 }
310
311