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