• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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