rsdCore.cpp revision ed8844c7275bcb80bf22e31ac47baf4ca231df94
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        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    ALOGV("%p Launching thread(s), CPUs %i", rsc, cpu);
231    if (cpu < 2) cpu = 0;
232
233    dc->mWorkers.mCount = (uint32_t)cpu;
234    dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t));
235    dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t));
236    dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount];
237    dc->mWorkers.mLaunchCallback = NULL;
238
239    dc->mWorkers.mCompleteSignal.init();
240
241    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
242    android_atomic_release_store(0, &dc->mWorkers.mLaunchCount);
243
244    pthread_attr_t threadAttr;
245    status = pthread_attr_init(&threadAttr);
246    if (status) {
247        ALOGE("Failed to init thread attribute.");
248        return false;
249    }
250
251    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
252        status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc);
253        if (status) {
254            dc->mWorkers.mCount = ct;
255            ALOGE("Created fewer than expected number of RS threads.");
256            break;
257        }
258    }
259    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
260        usleep(100);
261    }
262
263    pthread_attr_destroy(&threadAttr);
264    return true;
265}
266
267
268void SetPriority(const Context *rsc, int32_t priority) {
269    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
270    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
271        setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority);
272    }
273    if (dc->mHasGraphics) {
274        rsdGLSetPriority(rsc, priority);
275    }
276}
277
278void Shutdown(Context *rsc) {
279    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
280
281    dc->mExit = true;
282    dc->mWorkers.mLaunchData = NULL;
283    dc->mWorkers.mLaunchCallback = NULL;
284    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
285    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
286        dc->mWorkers.mLaunchSignals[ct].set();
287    }
288    int status;
289    void *res;
290    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
291        status = pthread_join(dc->mWorkers.mThreadId[ct], &res);
292    }
293    rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0);
294
295    // Global structure cleanup.
296    pthread_mutex_lock(&rsdgInitMutex);
297    --rsdgThreadTLSKeyCount;
298    if (!rsdgThreadTLSKeyCount) {
299        pthread_key_delete(rsdgThreadTLSKey);
300    }
301    pthread_mutex_unlock(&rsdgInitMutex);
302
303}
304
305