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