rsdCore.cpp revision 807fdc4b6f3fb893015ee136565d6151bb2332d3
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
40using namespace android;
41using namespace android::renderscript;
42
43static void Shutdown(Context *rsc);
44static void SetPriority(const Context *rsc, int32_t priority);
45
46static RsdHalFunctions FunctionTable = {
47    rsdGLInit,
48    rsdGLShutdown,
49    rsdGLSetSurface,
50    rsdGLSwap,
51
52    Shutdown,
53    NULL,
54    SetPriority,
55    {
56        rsdScriptInit,
57        rsdScriptInvokeFunction,
58        rsdScriptInvokeRoot,
59        rsdScriptInvokeForEach,
60        rsdScriptInvokeInit,
61        rsdScriptInvokeFreeChildren,
62        rsdScriptSetGlobalVar,
63        rsdScriptSetGlobalVarWithElemDims,
64        rsdScriptSetGlobalBind,
65        rsdScriptSetGlobalObj,
66        rsdScriptDestroy
67    },
68
69    {
70        rsdAllocationInit,
71        rsdAllocationDestroy,
72        rsdAllocationResize,
73        rsdAllocationSyncAll,
74        rsdAllocationMarkDirty,
75        rsdAllocationInitSurfaceTexture,
76        rsdAllocationSetSurfaceTexture,
77        rsdAllocationIoSend,
78        rsdAllocationIoReceive,
79        rsdAllocationData1D,
80        rsdAllocationData2D,
81        rsdAllocationData3D,
82        rsdAllocationRead1D,
83        rsdAllocationRead2D,
84        rsdAllocationRead3D,
85        rsdAllocationLock1D,
86        rsdAllocationUnlock1D,
87        rsdAllocationData1D_alloc,
88        rsdAllocationData2D_alloc,
89        rsdAllocationData3D_alloc,
90        rsdAllocationElementData1D,
91        rsdAllocationElementData2D
92    },
93
94
95    {
96        rsdProgramStoreInit,
97        rsdProgramStoreSetActive,
98        rsdProgramStoreDestroy
99    },
100
101    {
102        rsdProgramRasterInit,
103        rsdProgramRasterSetActive,
104        rsdProgramRasterDestroy
105    },
106
107    {
108        rsdProgramVertexInit,
109        rsdProgramVertexSetActive,
110        rsdProgramVertexDestroy
111    },
112
113    {
114        rsdProgramFragmentInit,
115        rsdProgramFragmentSetActive,
116        rsdProgramFragmentDestroy
117    },
118
119    {
120        rsdMeshInit,
121        rsdMeshDraw,
122        rsdMeshDestroy
123    },
124
125    {
126        rsdPathInitStatic,
127        rsdPathInitDynamic,
128        rsdPathDraw,
129        rsdPathDestroy
130    },
131
132    {
133        rsdSamplerInit,
134        rsdSamplerDestroy
135    },
136
137    {
138        rsdFrameBufferInit,
139        rsdFrameBufferSetActive,
140        rsdFrameBufferDestroy
141    },
142
143};
144
145pthread_key_t rsdgThreadTLSKey = 0;
146uint32_t rsdgThreadTLSKeyCount = 0;
147pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER;
148
149
150static void * HelperThreadProc(void *vrsc) {
151    Context *rsc = static_cast<Context *>(vrsc);
152    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
153
154
155    uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount);
156
157    //ALOGV("RS helperThread starting %p idx=%i", rsc, idx);
158
159    dc->mWorkers.mLaunchSignals[idx].init();
160    dc->mWorkers.mNativeThreadId[idx] = gettid();
161
162    int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
163    if (status) {
164        ALOGE("pthread_setspecific %i", status);
165    }
166
167#if 0
168    typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t;
169    cpu_set_t cpuset;
170    memset(&cpuset, 0, sizeof(cpuset));
171    cpuset.bits[idx / 64] |= 1ULL << (idx % 64);
172    int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx],
173              sizeof(cpuset), &cpuset);
174    ALOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret));
175#endif
176
177    while (!dc->mExit) {
178        dc->mWorkers.mLaunchSignals[idx].wait();
179        if (dc->mWorkers.mLaunchCallback) {
180           dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx);
181        }
182        android_atomic_dec(&dc->mWorkers.mRunningCount);
183        dc->mWorkers.mCompleteSignal.set();
184    }
185
186    //ALOGV("RS helperThread exited %p idx=%i", rsc, idx);
187    return NULL;
188}
189
190void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) {
191    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
192
193    dc->mWorkers.mLaunchData = data;
194    dc->mWorkers.mLaunchCallback = cbk;
195    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
196    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
197        dc->mWorkers.mLaunchSignals[ct].set();
198    }
199    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
200        dc->mWorkers.mCompleteSignal.wait();
201    }
202}
203
204bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) {
205    rsc->mHal.funcs = FunctionTable;
206
207    RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal));
208    if (!dc) {
209        ALOGE("Calloc for driver hal failed.");
210        return false;
211    }
212    rsc->mHal.drv = dc;
213
214    pthread_mutex_lock(&rsdgInitMutex);
215    if (!rsdgThreadTLSKeyCount) {
216        int status = pthread_key_create(&rsdgThreadTLSKey, NULL);
217        if (status) {
218            ALOGE("Failed to init thread tls key.");
219            pthread_mutex_unlock(&rsdgInitMutex);
220            return false;
221        }
222    }
223    rsdgThreadTLSKeyCount++;
224    pthread_mutex_unlock(&rsdgInitMutex);
225
226    dc->mTlsStruct.mContext = rsc;
227    dc->mTlsStruct.mScript = NULL;
228    int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
229    if (status) {
230        ALOGE("pthread_setspecific %i", status);
231    }
232
233
234    int cpu = sysconf(_SC_NPROCESSORS_ONLN);
235    if(rsc->props.mDebugMaxThreads && (cpu > (int)rsc->props.mDebugMaxThreads)) {
236        cpu = rsc->props.mDebugMaxThreads;
237    }
238    if (cpu < 2) {
239        cpu = 0;
240    }
241    ALOGV("%p Launching thread(s), CPUs %i", rsc, cpu);
242
243    dc->mWorkers.mCount = (uint32_t)cpu;
244    dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t));
245    dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t));
246    dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount];
247    dc->mWorkers.mLaunchCallback = NULL;
248
249    dc->mWorkers.mCompleteSignal.init();
250
251    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
252    android_atomic_release_store(0, &dc->mWorkers.mLaunchCount);
253
254    pthread_attr_t threadAttr;
255    status = pthread_attr_init(&threadAttr);
256    if (status) {
257        ALOGE("Failed to init thread attribute.");
258        return false;
259    }
260
261    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
262        status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc);
263        if (status) {
264            dc->mWorkers.mCount = ct;
265            ALOGE("Created fewer than expected number of RS threads.");
266            break;
267        }
268    }
269    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
270        usleep(100);
271    }
272
273    pthread_attr_destroy(&threadAttr);
274    return true;
275}
276
277
278void SetPriority(const Context *rsc, int32_t priority) {
279    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
280    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
281        setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority);
282    }
283    if (dc->mHasGraphics) {
284        rsdGLSetPriority(rsc, priority);
285    }
286}
287
288void Shutdown(Context *rsc) {
289    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
290
291    dc->mExit = true;
292    dc->mWorkers.mLaunchData = NULL;
293    dc->mWorkers.mLaunchCallback = NULL;
294    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
295    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
296        dc->mWorkers.mLaunchSignals[ct].set();
297    }
298    void *res;
299    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
300        pthread_join(dc->mWorkers.mThreadId[ct], &res);
301    }
302    rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0);
303
304    // Global structure cleanup.
305    pthread_mutex_lock(&rsdgInitMutex);
306    --rsdgThreadTLSKeyCount;
307    if (!rsdgThreadTLSKeyCount) {
308        pthread_key_delete(rsdgThreadTLSKey);
309    }
310    pthread_mutex_unlock(&rsdgInitMutex);
311
312}
313
314