rsdCore.cpp revision 57dc11a5eb5a92d2bc7070ad3392b12047dd9adc
1/* 2 * Copyright (C) 2011-2012 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 "rsdPath.h" 22#include "rsdProgramStore.h" 23#include "rsdProgramRaster.h" 24#include "rsdProgramVertex.h" 25#include "rsdProgramFragment.h" 26#include "rsdMesh.h" 27#include "rsdSampler.h" 28#include "rsdFrameBuffer.h" 29 30#include <malloc.h> 31#include "rsContext.h" 32 33#include <sys/types.h> 34#include <sys/resource.h> 35#include <sched.h> 36#include <cutils/properties.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 rsdScriptInvokeFreeChildren, 63 rsdScriptSetGlobalVar, 64 rsdScriptSetGlobalVarWithElemDims, 65 rsdScriptSetGlobalBind, 66 rsdScriptSetGlobalObj, 67 rsdScriptDestroy 68 }, 69 70 { 71 rsdAllocationInit, 72 rsdAllocationDestroy, 73 rsdAllocationResize, 74 rsdAllocationSyncAll, 75 rsdAllocationMarkDirty, 76 rsdAllocationInitSurfaceTexture, 77 rsdAllocationSetSurfaceTexture, 78 rsdAllocationIoSend, 79 rsdAllocationIoReceive, 80 rsdAllocationData1D, 81 rsdAllocationData2D, 82 rsdAllocationData3D, 83 rsdAllocationRead1D, 84 rsdAllocationRead2D, 85 rsdAllocationRead3D, 86 rsdAllocationLock1D, 87 rsdAllocationUnlock1D, 88 rsdAllocationData1D_alloc, 89 rsdAllocationData2D_alloc, 90 rsdAllocationData3D_alloc, 91 rsdAllocationElementData1D, 92 rsdAllocationElementData2D 93 }, 94 95 96 { 97 rsdProgramStoreInit, 98 rsdProgramStoreSetActive, 99 rsdProgramStoreDestroy 100 }, 101 102 { 103 rsdProgramRasterInit, 104 rsdProgramRasterSetActive, 105 rsdProgramRasterDestroy 106 }, 107 108 { 109 rsdProgramVertexInit, 110 rsdProgramVertexSetActive, 111 rsdProgramVertexDestroy 112 }, 113 114 { 115 rsdProgramFragmentInit, 116 rsdProgramFragmentSetActive, 117 rsdProgramFragmentDestroy 118 }, 119 120 { 121 rsdMeshInit, 122 rsdMeshDraw, 123 rsdMeshDestroy 124 }, 125 126 { 127 rsdPathInitStatic, 128 rsdPathInitDynamic, 129 rsdPathDraw, 130 rsdPathDestroy 131 }, 132 133 { 134 rsdSamplerInit, 135 rsdSamplerDestroy 136 }, 137 138 { 139 rsdFrameBufferInit, 140 rsdFrameBufferSetActive, 141 rsdFrameBufferDestroy 142 }, 143 144}; 145 146pthread_key_t rsdgThreadTLSKey = 0; 147uint32_t rsdgThreadTLSKeyCount = 0; 148pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER; 149 150 151static void * HelperThreadProc(void *vrsc) { 152 Context *rsc = static_cast<Context *>(vrsc); 153 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 154 155 156 uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount); 157 158 //ALOGV("RS helperThread starting %p idx=%i", rsc, idx); 159 160 dc->mWorkers.mLaunchSignals[idx].init(); 161 dc->mWorkers.mNativeThreadId[idx] = gettid(); 162 163 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct); 164 if (status) { 165 ALOGE("pthread_setspecific %i", status); 166 } 167 168#if 0 169 typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t; 170 cpu_set_t cpuset; 171 memset(&cpuset, 0, sizeof(cpuset)); 172 cpuset.bits[idx / 64] |= 1ULL << (idx % 64); 173 int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx], 174 sizeof(cpuset), &cpuset); 175 ALOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret)); 176#endif 177 178 while (!dc->mExit) { 179 dc->mWorkers.mLaunchSignals[idx].wait(); 180 if (dc->mWorkers.mLaunchCallback) { 181 dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx); 182 } 183 android_atomic_dec(&dc->mWorkers.mRunningCount); 184 dc->mWorkers.mCompleteSignal.set(); 185 } 186 187 //ALOGV("RS helperThread exited %p idx=%i", rsc, idx); 188 return NULL; 189} 190 191void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) { 192 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 193 194 dc->mWorkers.mLaunchData = data; 195 dc->mWorkers.mLaunchCallback = cbk; 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 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { 201 dc->mWorkers.mCompleteSignal.wait(); 202 } 203} 204 205bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) { 206 rsc->mHal.funcs = FunctionTable; 207 208 RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal)); 209 if (!dc) { 210 ALOGE("Calloc for driver hal failed."); 211 return false; 212 } 213 rsc->mHal.drv = dc; 214 215 pthread_mutex_lock(&rsdgInitMutex); 216 if (!rsdgThreadTLSKeyCount) { 217 int status = pthread_key_create(&rsdgThreadTLSKey, NULL); 218 if (status) { 219 ALOGE("Failed to init thread tls key."); 220 pthread_mutex_unlock(&rsdgInitMutex); 221 return false; 222 } 223 } 224 rsdgThreadTLSKeyCount++; 225 pthread_mutex_unlock(&rsdgInitMutex); 226 227 dc->mTlsStruct.mContext = rsc; 228 dc->mTlsStruct.mScript = NULL; 229 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct); 230 if (status) { 231 ALOGE("pthread_setspecific %i", status); 232 } 233 234 235 int cpu = sysconf(_SC_NPROCESSORS_ONLN); 236 if(rsc->props.mDebugMaxThreads && (cpu > (int)rsc->props.mDebugMaxThreads)) { 237 cpu = rsc->props.mDebugMaxThreads; 238 } 239 if (cpu < 2) { 240 cpu = 0; 241 } 242 ALOGV("%p Launching thread(s), CPUs %i", rsc, cpu); 243 244 dc->mWorkers.mCount = (uint32_t)cpu; 245 dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t)); 246 dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t)); 247 dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount]; 248 dc->mWorkers.mLaunchCallback = NULL; 249 250 dc->mWorkers.mCompleteSignal.init(); 251 252 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 253 android_atomic_release_store(0, &dc->mWorkers.mLaunchCount); 254 255 pthread_attr_t threadAttr; 256 status = pthread_attr_init(&threadAttr); 257 if (status) { 258 ALOGE("Failed to init thread attribute."); 259 return false; 260 } 261 262 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { 263 status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc); 264 if (status) { 265 dc->mWorkers.mCount = ct; 266 ALOGE("Created fewer than expected number of RS threads."); 267 break; 268 } 269 } 270 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { 271 usleep(100); 272 } 273 274 pthread_attr_destroy(&threadAttr); 275 return true; 276} 277 278 279void SetPriority(const Context *rsc, int32_t priority) { 280 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 281 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { 282 setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority); 283 } 284 if (dc->mHasGraphics) { 285 rsdGLSetPriority(rsc, priority); 286 } 287} 288 289void Shutdown(Context *rsc) { 290 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 291 292 dc->mExit = true; 293 dc->mWorkers.mLaunchData = NULL; 294 dc->mWorkers.mLaunchCallback = NULL; 295 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 296 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 297 dc->mWorkers.mLaunchSignals[ct].set(); 298 } 299 void *res; 300 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 301 pthread_join(dc->mWorkers.mThreadId[ct], &res); 302 } 303 rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0); 304 305 // Global structure cleanup. 306 pthread_mutex_lock(&rsdgInitMutex); 307 --rsdgThreadTLSKeyCount; 308 if (!rsdgThreadTLSKeyCount) { 309 pthread_key_delete(rsdgThreadTLSKey); 310 } 311 pthread_mutex_unlock(&rsdgInitMutex); 312 313} 314 315