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