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