diff options
-rw-r--r-- | cpu_ref/rsCpuExecutable.cpp | 57 | ||||
-rw-r--r-- | cpu_ref/rsCpuExecutable.h | 8 | ||||
-rw-r--r-- | cpu_ref/rsCpuScript.cpp | 11 | ||||
-rw-r--r-- | cpu_ref/rsCpuScriptGroup2.cpp | 47 |
4 files changed, 86 insertions, 37 deletions
diff --git a/cpu_ref/rsCpuExecutable.cpp b/cpu_ref/rsCpuExecutable.cpp index e2c27b55..867a2cd6 100644 --- a/cpu_ref/rsCpuExecutable.cpp +++ b/cpu_ref/rsCpuExecutable.cpp @@ -20,27 +20,6 @@ namespace renderscript { namespace { -// Create a len length string containing random characters from [A-Za-z0-9]. -static std::string getRandomString(size_t len) { - char buf[len + 1]; - for (size_t i = 0; i < len; i++) { - uint32_t r = arc4random() & 0xffff; - r %= 62; - if (r < 26) { - // lowercase - buf[i] = 'a' + r; - } else if (r < 52) { - // uppercase - buf[i] = 'A' + (r - 26); - } else { - // Use a number - buf[i] = '0' + (r - 52); - } - } - buf[len] = '\0'; - return std::string(buf); -} - // Check if a path exists and attempt to create it if it doesn't. static bool ensureCacheDirExists(const char *path) { if (access(path, R_OK | W_OK | X_OK) == 0) { @@ -151,7 +130,8 @@ const char* RsdCpuScriptImpl::BCC_EXE_PATH = "/system/bin/bcc"; void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir, const char *resName, - const char *nativeLibDir) { + const char *nativeLibDir, + bool* alreadyLoaded) { void *loaded = nullptr; #if defined(RS_COMPATIBILITY_LIB) && defined(__LP64__) @@ -162,7 +142,7 @@ void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir, // We should check if we can load the library from the standard app // location for shared libraries first. - loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName); + loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName, alreadyLoaded); if (loaded == nullptr) { ALOGE("Unable to open shared library (%s): %s", @@ -189,8 +169,28 @@ void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir, return loaded; } +String8 SharedLibraryUtils::getRandomString(size_t len) { + char buf[len + 1]; + for (size_t i = 0; i < len; i++) { + uint32_t r = arc4random() & 0xffff; + r %= 62; + if (r < 26) { + // lowercase + buf[i] = 'a' + r; + } else if (r < 52) { + // uppercase + buf[i] = 'A' + (r - 26); + } else { + // Use a number + buf[i] = '0' + (r - 52); + } + } + buf[len] = '\0'; + return String8(buf); +} + void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir, - const char *resName) { + const char *resName, bool *alreadyLoaded) { // Keep track of which .so libraries have been loaded. Once a library is // in the set (per-process granularity), we must instead make a copy of // the original shared object (randomly named .so file) and load that one @@ -208,6 +208,9 @@ void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDi // Common path is that we have not loaded this Script/library before. if (LoadedLibraries.find(origName) == LoadedLibraries.end()) { + if (alreadyLoaded != nullptr) { + *alreadyLoaded = false; + } loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL); if (loaded) { LoadedLibraries.insert(origName); @@ -215,6 +218,10 @@ void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDi return loaded; } + if (alreadyLoaded != nullptr) { + *alreadyLoaded = true; + } + std::string newName(cacheDir); // Append RS_CACHE_DIR only if it is not found in cacheDir @@ -234,7 +241,7 @@ void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDi newName.append("librs."); newName.append(resName); newName.append("#"); - newName.append(getRandomString(6)); // 62^6 potential filename variants. + newName.append(getRandomString(6).string()); // 62^6 potential filename variants. newName.append(".so"); int r = copyFile(newName.c_str(), origName); diff --git a/cpu_ref/rsCpuExecutable.h b/cpu_ref/rsCpuExecutable.h index 0464dacd..68809706 100644 --- a/cpu_ref/rsCpuExecutable.h +++ b/cpu_ref/rsCpuExecutable.h @@ -43,14 +43,18 @@ public: // For 64bit RS Support Lib, the shared lib path cannot be constructed from // cacheDir, so nativeLibDir is needed to load shared libs. static void* loadSharedLibrary(const char *cacheDir, const char *resName, - const char *nativeLibDir = nullptr); + const char *nativeLibDir = nullptr, + bool *alreadyLoaded = nullptr); + + // Create a len length string containing random characters from [A-Za-z0-9]. + static String8 getRandomString(size_t len); private: // Attempt to load the shared library from origName, but then fall back to // creating a copy of the shared library if necessary (to ensure instancing). // This function returns the dlopen()-ed handle if successful. static void *loadSOHelper(const char *origName, const char *cacheDir, - const char *resName); + const char *resName, bool* alreadyLoaded = nullptr); static const char* LD_EXE_PATH; static const char* RS_CACHE_DIR; diff --git a/cpu_ref/rsCpuScript.cpp b/cpu_ref/rsCpuScript.cpp index ea577bc8..bfed1f5a 100644 --- a/cpu_ref/rsCpuScript.cpp +++ b/cpu_ref/rsCpuScript.cpp @@ -883,15 +883,12 @@ const char* RsdCpuScriptImpl::getFieldName(uint32_t slot) const { RsdCpuScriptImpl::~RsdCpuScriptImpl() { #ifndef RS_COMPATIBILITY_LIB - if (mCompilerDriver) { - delete mCompilerDriver; - } + delete mCompilerDriver; #endif - if (mScriptExec != nullptr) { - delete mScriptExec; - } - if (mBoundAllocs) delete[] mBoundAllocs; + delete mScriptExec; + + delete[] mBoundAllocs; if (mScriptSO) { dlclose(mScriptSO); } diff --git a/cpu_ref/rsCpuScriptGroup2.cpp b/cpu_ref/rsCpuScriptGroup2.cpp index 8923c651..bf014031 100644 --- a/cpu_ref/rsCpuScriptGroup2.cpp +++ b/cpu_ref/rsCpuScriptGroup2.cpp @@ -156,6 +156,7 @@ CpuScriptGroup2Impl::CpuScriptGroup2Impl(RsdCpuReferenceImpl *cpuRefImpl, mExecutable(nullptr), mScriptObj(nullptr) { rsAssert(!mGroup->mClosures.empty()); + mCpuRefImpl->lockMutex(); Batch* batch = new Batch(this, "Batch0"); int i = 0; for (Closure* closure: mGroup->mClosures) { @@ -192,6 +193,7 @@ CpuScriptGroup2Impl::CpuScriptGroup2Impl(RsdCpuReferenceImpl *cpuRefImpl, } } #endif // RS_COMPATIBILITY_LIB + mCpuRefImpl->unlockMutex(); } void Batch::resolveFuncPtr(void* sharedObj) { @@ -279,6 +281,9 @@ void setupCompileArguments( } args->push_back("-output_path"); args->push_back(outputDir); + + // The output filename has to be the last, in case we need to pop it out and + // replace with a different name. args->push_back("-o"); args->push_back(outputFileName); } @@ -396,15 +401,41 @@ void CpuScriptGroup2Impl::compile(const char* cacheDir) { // Try to load a shared lib from code cache matching filename and checksum //===--------------------------------------------------------------------===// - mScriptObj = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName); + bool alreadyLoaded = false; + std::string cloneName; + + mScriptObj = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName, nullptr, + &alreadyLoaded); if (mScriptObj != nullptr) { + // A shared library named resName is found in code cache directory + // cacheDir, and loaded with the handle stored in mScriptObj. + mExecutable = ScriptExecutable::createFromSharedObject( getCpuRefImpl()->getContext(), mScriptObj, checksum); + if (mExecutable != nullptr) { + // The loaded shared library in mScriptObj has a matching checksum. + // An executable object has been created. return; - } else { - ALOGE("Failed to create an executable object from so file"); } + + ALOGV("Failed to create an executable object from so file due to " + "mismatching checksum"); + + if (alreadyLoaded) { + // The shared object found in code cache has already been loaded. + // A different file name is needed for the new shared library, to + // avoid corrupting the currently loaded instance. + + cloneName.append(resName); + cloneName.append("#"); + cloneName.append(SharedLibraryUtils::getRandomString(6).string()); + + // The last element in arguments is the output filename. + arguments.pop_back(); + arguments.push_back(cloneName.c_str()); + } + dlclose(mScriptObj); mScriptObj = nullptr; } @@ -443,6 +474,16 @@ void CpuScriptGroup2Impl::compile(const char* cacheDir) { return; } + if (alreadyLoaded) { + // Delete the temporary, random-named file that we created to avoid + // interfering with an already loaded shared library. + string cloneFilePath(cacheDir); + cloneFilePath.append("/"); + cloneFilePath.append(cloneName.c_str()); + cloneFilePath.append(".so"); + unlink(cloneFilePath.c_str()); + } + mExecutable = ScriptExecutable::createFromSharedObject( getCpuRefImpl()->getContext(), mScriptObj); |