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