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 41 using namespace android; 42 using namespace android::renderscript; 43 44 static void Shutdown(Context *rsc); 45 static void SetPriority(const Context *rsc, int32_t priority); 46 static void initForEach(outer_foreach_t* forEachLaunch); 47 48 static RsdHalFunctions FunctionTable = { 49 rsdGLInit, 50 rsdGLShutdown, 51 rsdGLSetSurface, 52 rsdGLSwap, 53 54 Shutdown, 55 NULL, 56 SetPriority, 57 { 58 rsdScriptInit, 59 rsdScriptInvokeFunction, 60 rsdScriptInvokeRoot, 61 rsdScriptInvokeForEach, 62 rsdScriptInvokeInit, 63 rsdScriptInvokeFreeChildren, 64 rsdScriptSetGlobalVar, 65 rsdScriptSetGlobalBind, 66 rsdScriptSetGlobalObj, 67 rsdScriptDestroy 68 }, 69 70 { 71 rsdAllocationInit, 72 rsdAllocationDestroy, 73 rsdAllocationResize, 74 rsdAllocationSyncAll, 75 rsdAllocationMarkDirty, 76 rsdAllocationData1D, 77 rsdAllocationData2D, 78 rsdAllocationData3D, 79 rsdAllocationData1D_alloc, 80 rsdAllocationData2D_alloc, 81 rsdAllocationData3D_alloc, 82 rsdAllocationElementData1D, 83 rsdAllocationElementData2D 84 }, 85 86 87 { 88 rsdProgramStoreInit, 89 rsdProgramStoreSetActive, 90 rsdProgramStoreDestroy 91 }, 92 93 { 94 rsdProgramRasterInit, 95 rsdProgramRasterSetActive, 96 rsdProgramRasterDestroy 97 }, 98 99 { 100 rsdProgramVertexInit, 101 rsdProgramVertexSetActive, 102 rsdProgramVertexDestroy 103 }, 104 105 { 106 rsdProgramFragmentInit, 107 rsdProgramFragmentSetActive, 108 rsdProgramFragmentDestroy 109 }, 110 111 { 112 rsdMeshInit, 113 rsdMeshDraw, 114 rsdMeshDestroy 115 }, 116 117 { 118 rsdSamplerInit, 119 rsdSamplerDestroy 120 }, 121 122 { 123 rsdFrameBufferInit, 124 rsdFrameBufferSetActive, 125 rsdFrameBufferDestroy 126 }, 127 128 }; 129 130 pthread_key_t rsdgThreadTLSKey = 0; 131 uint32_t rsdgThreadTLSKeyCount = 0; 132 pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER; 133 134 135 static void * HelperThreadProc(void *vrsc) { 136 Context *rsc = static_cast<Context *>(vrsc); 137 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 138 139 140 uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount); 141 142 //LOGV("RS helperThread starting %p idx=%i", rsc, idx); 143 144 dc->mWorkers.mLaunchSignals[idx].init(); 145 dc->mWorkers.mNativeThreadId[idx] = gettid(); 146 147 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct); 148 if (status) { 149 LOGE("pthread_setspecific %i", status); 150 } 151 152 #if 0 153 typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t; 154 cpu_set_t cpuset; 155 memset(&cpuset, 0, sizeof(cpuset)); 156 cpuset.bits[idx / 64] |= 1ULL << (idx % 64); 157 int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx], 158 sizeof(cpuset), &cpuset); 159 LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret)); 160 #endif 161 162 while (!dc->mExit) { 163 dc->mWorkers.mLaunchSignals[idx].wait(); 164 if (dc->mWorkers.mLaunchCallback) { 165 dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx); 166 } 167 android_atomic_dec(&dc->mWorkers.mRunningCount); 168 dc->mWorkers.mCompleteSignal.set(); 169 } 170 171 //LOGV("RS helperThread exited %p idx=%i", rsc, idx); 172 return NULL; 173 } 174 175 void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) { 176 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 177 178 dc->mWorkers.mLaunchData = data; 179 dc->mWorkers.mLaunchCallback = cbk; 180 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 181 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 182 dc->mWorkers.mLaunchSignals[ct].set(); 183 } 184 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { 185 dc->mWorkers.mCompleteSignal.wait(); 186 } 187 } 188 189 bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) { 190 rsc->mHal.funcs = FunctionTable; 191 192 RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal)); 193 if (!dc) { 194 LOGE("Calloc for driver hal failed."); 195 return false; 196 } 197 rsc->mHal.drv = dc; 198 199 pthread_mutex_lock(&rsdgInitMutex); 200 if (!rsdgThreadTLSKeyCount) { 201 int status = pthread_key_create(&rsdgThreadTLSKey, NULL); 202 if (status) { 203 LOGE("Failed to init thread tls key."); 204 pthread_mutex_unlock(&rsdgInitMutex); 205 return false; 206 } 207 } 208 rsdgThreadTLSKeyCount++; 209 pthread_mutex_unlock(&rsdgInitMutex); 210 211 initForEach(dc->mForEachLaunch); 212 213 dc->mTlsStruct.mContext = rsc; 214 dc->mTlsStruct.mScript = NULL; 215 int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct); 216 if (status) { 217 LOGE("pthread_setspecific %i", status); 218 } 219 220 221 int cpu = sysconf(_SC_NPROCESSORS_ONLN); 222 LOGV("%p Launching thread(s), CPUs %i", rsc, cpu); 223 if (cpu < 2) cpu = 0; 224 225 dc->mWorkers.mCount = (uint32_t)cpu; 226 dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t)); 227 dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t)); 228 dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount]; 229 dc->mWorkers.mLaunchCallback = NULL; 230 231 dc->mWorkers.mCompleteSignal.init(); 232 233 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 234 android_atomic_release_store(0, &dc->mWorkers.mLaunchCount); 235 236 pthread_attr_t threadAttr; 237 status = pthread_attr_init(&threadAttr); 238 if (status) { 239 LOGE("Failed to init thread attribute."); 240 return false; 241 } 242 243 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { 244 status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc); 245 if (status) { 246 dc->mWorkers.mCount = ct; 247 LOGE("Created fewer than expected number of RS threads."); 248 break; 249 } 250 } 251 while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) { 252 usleep(100); 253 } 254 255 pthread_attr_destroy(&threadAttr); 256 return true; 257 } 258 259 260 void SetPriority(const Context *rsc, int32_t priority) { 261 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 262 for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) { 263 setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority); 264 } 265 } 266 267 void Shutdown(Context *rsc) { 268 RsdHal *dc = (RsdHal *)rsc->mHal.drv; 269 270 dc->mExit = true; 271 dc->mWorkers.mLaunchData = NULL; 272 dc->mWorkers.mLaunchCallback = NULL; 273 android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount); 274 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 275 dc->mWorkers.mLaunchSignals[ct].set(); 276 } 277 int status; 278 void *res; 279 for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) { 280 status = pthread_join(dc->mWorkers.mThreadId[ct], &res); 281 } 282 rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0); 283 284 // Global structure cleanup. 285 pthread_mutex_lock(&rsdgInitMutex); 286 --rsdgThreadTLSKeyCount; 287 if (!rsdgThreadTLSKeyCount) { 288 pthread_key_delete(rsdgThreadTLSKey); 289 } 290 pthread_mutex_unlock(&rsdgInitMutex); 291 292 } 293 294 static void rsdForEach17(const void *vRoot, 295 const android::renderscript::RsForEachStubParamStruct *p) { 296 typedef void (*fe)(const void *, uint32_t); 297 (*(fe*)vRoot)(p->in, p->y); 298 } 299 300 static void rsdForEach18(const void *vRoot, 301 const android::renderscript::RsForEachStubParamStruct *p) { 302 typedef void (*fe)(void *, uint32_t); 303 (*(fe*)vRoot)(p->out, p->y); 304 } 305 306 static void rsdForEach19(const void *vRoot, 307 const android::renderscript::RsForEachStubParamStruct *p) { 308 typedef void (*fe)(const void *, void *, uint32_t); 309 (*(fe*)vRoot)(p->in, p->out, p->y); 310 } 311 312 static void rsdForEach21(const void *vRoot, 313 const android::renderscript::RsForEachStubParamStruct *p) { 314 typedef void (*fe)(const void *, const void *, uint32_t); 315 (*(fe*)vRoot)(p->in, p->usr, p->y); 316 } 317 318 static void rsdForEach22(const void *vRoot, 319 const android::renderscript::RsForEachStubParamStruct *p) { 320 typedef void (*fe)(void *, const void *, uint32_t); 321 (*(fe*)vRoot)(p->out, p->usr, p->y); 322 } 323 324 static void rsdForEach23(const void *vRoot, 325 const android::renderscript::RsForEachStubParamStruct *p) { 326 typedef void (*fe)(const void *, void *, const void *, uint32_t); 327 (*(fe*)vRoot)(p->in, p->out, p->usr, p->y); 328 } 329 330 static void rsdForEach25(const void *vRoot, 331 const android::renderscript::RsForEachStubParamStruct *p) { 332 typedef void (*fe)(const void *, uint32_t, uint32_t); 333 (*(fe*)vRoot)(p->in, p->x, p->y); 334 } 335 336 static void rsdForEach26(const void *vRoot, 337 const android::renderscript::RsForEachStubParamStruct *p) { 338 typedef void (*fe)(void *, uint32_t, uint32_t); 339 (*(fe*)vRoot)(p->out, p->x, p->y); 340 } 341 342 static void rsdForEach27(const void *vRoot, 343 const android::renderscript::RsForEachStubParamStruct *p) { 344 typedef void (*fe)(const void *, void *, uint32_t, uint32_t); 345 (*(fe*)vRoot)(p->in, p->out, p->x, p->y); 346 } 347 348 static void rsdForEach29(const void *vRoot, 349 const android::renderscript::RsForEachStubParamStruct *p) { 350 typedef void (*fe)(const void *, const void *, uint32_t, uint32_t); 351 (*(fe*)vRoot)(p->in, p->usr, p->x, p->y); 352 } 353 354 static void rsdForEach30(const void *vRoot, 355 const android::renderscript::RsForEachStubParamStruct *p) { 356 typedef void (*fe)(void *, const void *, uint32_t, uint32_t); 357 (*(fe*)vRoot)(p->out, p->usr, p->x, p->y); 358 } 359 360 static void rsdForEach31(const void *vRoot, 361 const android::renderscript::RsForEachStubParamStruct *p) { 362 typedef void (*fe)(const void *, void *, const void *, uint32_t, uint32_t); 363 (*(fe*)vRoot)(p->in, p->out, p->usr, p->x, p->y); 364 } 365 366 367 static void initForEach(outer_foreach_t* forEachLaunch) { 368 rsAssert(forEachLaunch); 369 forEachLaunch[0x00] = NULL; 370 forEachLaunch[0x01] = rsdForEach31; // in 371 forEachLaunch[0x02] = rsdForEach30; // out 372 forEachLaunch[0x03] = rsdForEach31; // in, out 373 forEachLaunch[0x04] = NULL; 374 forEachLaunch[0x05] = rsdForEach29; // in, usr 375 forEachLaunch[0x06] = rsdForEach30; // out, usr 376 forEachLaunch[0x07] = rsdForEach31; // in, out, usr 377 forEachLaunch[0x08] = NULL; 378 forEachLaunch[0x09] = rsdForEach25; // in, x 379 forEachLaunch[0x0a] = rsdForEach26; // out, x 380 forEachLaunch[0x0b] = rsdForEach27; // in, out, x 381 forEachLaunch[0x0c] = NULL; 382 forEachLaunch[0x0d] = rsdForEach29; // in, usr, x 383 forEachLaunch[0x0e] = rsdForEach30; // out, usr, x 384 forEachLaunch[0x0f] = rsdForEach31; // in, out, usr, x 385 forEachLaunch[0x10] = NULL; 386 forEachLaunch[0x11] = rsdForEach17; // in y 387 forEachLaunch[0x12] = rsdForEach18; // out, y 388 forEachLaunch[0x13] = rsdForEach19; // in, out, y 389 forEachLaunch[0x14] = NULL; 390 forEachLaunch[0x15] = rsdForEach21; // in, usr, y 391 forEachLaunch[0x16] = rsdForEach22; // out, usr, y 392 forEachLaunch[0x17] = rsdForEach23; // in, out, usr, y 393 forEachLaunch[0x18] = NULL; 394 forEachLaunch[0x19] = rsdForEach25; // in, x, y 395 forEachLaunch[0x1a] = rsdForEach26; // out, x, y 396 forEachLaunch[0x1b] = rsdForEach27; // in, out, x, y 397 forEachLaunch[0x1c] = NULL; 398 forEachLaunch[0x1d] = rsdForEach29; // in, usr, x, y 399 forEachLaunch[0x1e] = rsdForEach30; // out, usr, x, y 400 forEachLaunch[0x1f] = rsdForEach31; // in, out, usr, x, y 401 } 402 403