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