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