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