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