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