rsdCore.cpp revision 87fe59a2f4d4c74539bfa0bff5f9a7e320e99415
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
23#include <malloc.h>
24#include "rsContext.h"
25
26#include <sys/types.h>
27#include <sys/resource.h>
28#include <sched.h>
29#include <cutils/properties.h>
30#include <cutils/sched_policy.h>
31#include <sys/syscall.h>
32#include <string.h>
33
34using namespace android;
35using namespace android::renderscript;
36
37static void Shutdown(Context *rsc);
38static void SetPriority(const Context *rsc, int32_t priority);
39
40static RsdHalFunctions FunctionTable = {
41    rsdGLInit,
42    rsdGLShutdown,
43    rsdGLSetSurface,
44    rsdGLSwap,
45
46    Shutdown,
47    NULL,
48    SetPriority,
49    {
50        rsdScriptInit,
51        rsdScriptInvokeFunction,
52        rsdScriptInvokeRoot,
53        rsdScriptInvokeForEach,
54        rsdScriptInvokeInit,
55        rsdScriptSetGlobalVar,
56        rsdScriptSetGlobalBind,
57        rsdScriptSetGlobalObj,
58        rsdScriptDestroy
59    },
60
61
62    {
63        rsdProgramStoreInit,
64        rsdProgramStoreSetActive,
65        rsdProgramStoreDestroy
66    },
67
68    {
69        rsdProgramRasterInit,
70        rsdProgramRasterSetActive,
71        rsdProgramRasterDestroy
72    }
73
74};
75
76
77
78static void * HelperThreadProc(void *vrsc) {
79    Context *rsc = static_cast<Context *>(vrsc);
80    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
81
82
83    uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount);
84
85    //LOGV("RS helperThread starting %p idx=%i", rsc, idx);
86
87    dc->mWorkers.mLaunchSignals[idx].init();
88    dc->mWorkers.mNativeThreadId[idx] = gettid();
89
90#if 0
91    typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t;
92    cpu_set_t cpuset;
93    memset(&cpuset, 0, sizeof(cpuset));
94    cpuset.bits[idx / 64] |= 1ULL << (idx % 64);
95    int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx],
96              sizeof(cpuset), &cpuset);
97    LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret));
98#endif
99
100    int status = pthread_setspecific(rsc->gThreadTLSKey, rsc->mTlsStruct);
101    if (status) {
102        LOGE("pthread_setspecific %i", status);
103    }
104
105    while (!dc->mExit) {
106        dc->mWorkers.mLaunchSignals[idx].wait();
107        if (dc->mWorkers.mLaunchCallback) {
108           dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx);
109        }
110        android_atomic_dec(&dc->mWorkers.mRunningCount);
111        dc->mWorkers.mCompleteSignal.set();
112    }
113
114    //LOGV("RS helperThread exited %p idx=%i", rsc, idx);
115    return NULL;
116}
117
118void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) {
119    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
120
121    dc->mWorkers.mLaunchData = data;
122    dc->mWorkers.mLaunchCallback = cbk;
123    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
124    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
125        dc->mWorkers.mLaunchSignals[ct].set();
126    }
127    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
128        dc->mWorkers.mCompleteSignal.wait();
129    }
130}
131
132bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) {
133    rsc->mHal.funcs = FunctionTable;
134
135    RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal));
136    if (!dc) {
137        LOGE("Calloc for driver hal failed.");
138        return false;
139    }
140    rsc->mHal.drv = dc;
141
142
143    int cpu = sysconf(_SC_NPROCESSORS_ONLN);
144    LOGV("RS Launching thread(s), reported CPU count %i", cpu);
145    if (cpu < 2) cpu = 0;
146
147    dc->mWorkers.mCount = (uint32_t)cpu;
148    dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t));
149    dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t));
150    dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount];
151    dc->mWorkers.mLaunchCallback = NULL;
152
153    dc->mWorkers.mCompleteSignal.init();
154
155    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
156    android_atomic_release_store(0, &dc->mWorkers.mLaunchCount);
157
158    int status;
159    pthread_attr_t threadAttr;
160    status = pthread_attr_init(&threadAttr);
161    if (status) {
162        LOGE("Failed to init thread attribute.");
163        return false;
164    }
165
166    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
167        status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc);
168        if (status) {
169            dc->mWorkers.mCount = ct;
170            LOGE("Created fewer than expected number of RS threads.");
171            break;
172        }
173    }
174    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
175        usleep(100);
176    }
177
178    pthread_attr_destroy(&threadAttr);
179    return true;
180}
181
182
183void SetPriority(const Context *rsc, int32_t priority) {
184    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
185    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
186        setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority);
187    }
188}
189
190void Shutdown(Context *rsc) {
191    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
192
193    dc->mExit = true;
194    dc->mWorkers.mLaunchData = NULL;
195    dc->mWorkers.mLaunchCallback = NULL;
196    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
197    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
198        dc->mWorkers.mLaunchSignals[ct].set();
199    }
200    int status;
201    void *res;
202    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
203        status = pthread_join(dc->mWorkers.mThreadId[ct], &res);
204    }
205    rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0);
206}
207
208
209