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