diff options
Diffstat (limited to 'cpu_ref')
-rw-r--r-- | cpu_ref/rsCpuExecutable.cpp | 41 | ||||
-rw-r--r-- | cpu_ref/rsCpuExecutable.h | 14 | ||||
-rw-r--r-- | cpu_ref/rsCpuScript.cpp | 38 | ||||
-rw-r--r-- | cpu_ref/rsCpuScript.h | 22 | ||||
-rw-r--r-- | cpu_ref/rsCpuScriptGroup2.cpp | 20 |
5 files changed, 103 insertions, 32 deletions
diff --git a/cpu_ref/rsCpuExecutable.cpp b/cpu_ref/rsCpuExecutable.cpp index a79f671a..83ef7574 100644 --- a/cpu_ref/rsCpuExecutable.cpp +++ b/cpu_ref/rsCpuExecutable.cpp @@ -60,7 +60,8 @@ static int copyFile(const char *dstFile, const char *srcFile) { } static std::string findSharedObjectName(const char *cacheDir, - const char *resName) { + const char *resName, + const bool reuse = true) { std::string scriptSOName(cacheDir); #if defined(RS_COMPATIBILITY_LIB) && !defined(__LP64__) size_t cutPos = scriptSOName.rfind("cache"); @@ -74,6 +75,20 @@ static std::string findSharedObjectName(const char *cacheDir, scriptSOName.append("/librs."); #endif // RS_COMPATIBILITY_LIB scriptSOName.append(resName); + if (!reuse) { + // If the generated shared library is not reused, e.g., with a debug + // context or forced by a system property, multiple threads may read + // and write the shared library at the same time. To avoid the race + // on the generated shared library, delete it before finishing script + // initialization. To avoid deleting a file generated by a regular + // context, use a special suffix here. + // Because the script initialization is guarded by a lock from the Java + // API, it is safe to name this file with a consistent name and suffix + // and delete it after loading. The same lock has also prevented write- + // write races on the .so during script initialization even if reuse is + // true. + scriptSOName.append("#delete_after_load"); + } scriptSOName.append(".so"); return scriptSOName; @@ -88,8 +103,13 @@ const char* SharedLibraryUtils::RS_CACHE_DIR = "com.android.renderscript.cache"; bool SharedLibraryUtils::createSharedLibrary(const char *driverName, const char *cacheDir, - const char *resName) { - std::string sharedLibName = findSharedObjectName(cacheDir, resName); + const char *resName, + const bool reuse, + std::string *fullPath) { + std::string sharedLibName = findSharedObjectName(cacheDir, resName, reuse); + if (fullPath) { + *fullPath = sharedLibName; + } std::string objFileName = cacheDir; objFileName.append("/"); objFileName.append(resName); @@ -125,6 +145,21 @@ bool SharedLibraryUtils::createSharedLibrary(const char *driverName, const char* RsdCpuScriptImpl::BCC_EXE_PATH = "/system/bin/bcc"; +void* SharedLibraryUtils::loadAndDeleteSharedLibrary(const char *fullPath) { + void *loaded = dlopen(fullPath, RTLD_NOW | RTLD_LOCAL); + if (loaded == nullptr) { + ALOGE("Unable to open shared library (%s): %s", fullPath, dlerror()); + return nullptr; + } + + int r = unlink(fullPath); + if (r != 0) { + ALOGE("Could not unlink copy %s", fullPath); + return nullptr; + } + return loaded; +} + void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir, const char *resName, const char *nativeLibDir, diff --git a/cpu_ref/rsCpuExecutable.h b/cpu_ref/rsCpuExecutable.h index ee58e377..82cf7742 100644 --- a/cpu_ref/rsCpuExecutable.h +++ b/cpu_ref/rsCpuExecutable.h @@ -31,9 +31,14 @@ class Context; class SharedLibraryUtils { public: #ifndef RS_COMPATIBILITY_LIB + // Creates a shared library in cacheDir for the bitcode named resName. + // If reuse is false and SOPath is not nullptr, saves the filename + // used for the shared library in SOPath. static bool createSharedLibrary(const char* driverName, const char* cacheDir, - const char* resName); + const char* resName, + const bool reuse = true, + std::string *SOPath = nullptr); #endif // Load the shared library referred to by cacheDir and resName. If we have @@ -48,6 +53,13 @@ public: const char *nativeLibDir = nullptr, bool *alreadyLoaded = nullptr); + // Load the shared library referred to by fullPath, and delete it right + // after loading it. Files loaded by this function are only used once, e.g., + // shared libraries generated for scripts in a debug context. Deleting them + // is OK in this case since the shared libraries have already been dlopened. + // Deletion is also required because such files are not intended for reuse. + static void* loadAndDeleteSharedLibrary(const char *fullPath); + // Create a len length string containing random characters from [A-Za-z0-9]. static std::string getRandomString(size_t len); diff --git a/cpu_ref/rsCpuScript.cpp b/cpu_ref/rsCpuScript.cpp index 545e92f3..dec9ab29 100644 --- a/cpu_ref/rsCpuScript.cpp +++ b/cpu_ref/rsCpuScript.cpp @@ -57,24 +57,6 @@ static bool allocationLODIsNull(const android::renderscript::Allocation *alloc) #ifndef RS_COMPATIBILITY_LIB -static bool is_force_recompile() { - char buf[PROP_VALUE_MAX]; - - // Re-compile if floating point precision has been overridden. - android::renderscript::property_get("debug.rs.precision", buf, ""); - if (buf[0] != '\0') { - return true; - } - - // Re-compile if debug.rs.forcerecompile is set. - android::renderscript::property_get("debug.rs.forcerecompile", buf, "0"); - if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) { - return true; - } else { - return false; - } -} - static void setCompileArguments(std::vector<const char*>* args, const std::string& bcFileName, const char* cacheDir, const char* resName, @@ -381,7 +363,8 @@ bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir, compileArguments.push_back(checksumStr.c_str()); compileArguments.push_back(nullptr); - if (!is_force_recompile() && !useRSDebugContext) { + const bool reuse = !is_force_recompile() && !useRSDebugContext; + if (reuse) { mScriptSO = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName); // Read RS info from the shared object to detect checksum mismatch @@ -391,8 +374,8 @@ bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir, } } - // If we can't, it's either not there or out of date. We compile the bit code and try loading - // again. + // If reuse is desired and we can't, it's either not there or out of date. + // We compile the bit code and try loading again. if (mScriptSO == nullptr) { if (!compileBitcode(bcFileName, (const char*)bitcode, bitcodeSize, compileArguments)) @@ -402,14 +385,21 @@ bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir, return false; } - if (!SharedLibraryUtils::createSharedLibrary(mCtx->getContext()->getDriverName(), - cacheDir, resName)) { + std::string SOPath; + + if (!SharedLibraryUtils::createSharedLibrary( + mCtx->getContext()->getDriverName(), cacheDir, resName, reuse, + &SOPath)) { ALOGE("Linker: Failed to link object file '%s'", resName); mCtx->unlockMutex(); return false; } - mScriptSO = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName); + if (reuse) { + mScriptSO = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName); + } else { + mScriptSO = SharedLibraryUtils::loadAndDeleteSharedLibrary(SOPath.c_str()); + } if (mScriptSO == nullptr) { ALOGE("Unable to load '%s'", resName); mCtx->unlockMutex(); diff --git a/cpu_ref/rsCpuScript.h b/cpu_ref/rsCpuScript.h index 1814d5ff..dc96f8ba 100644 --- a/cpu_ref/rsCpuScript.h +++ b/cpu_ref/rsCpuScript.h @@ -171,4 +171,26 @@ uint32_t constructBuildChecksum(uint8_t const *bitcode, size_t bitcodeSize, } // namespace android +namespace { + +inline bool is_force_recompile() { + char buf[PROP_VALUE_MAX]; + + // Re-compile if floating point precision has been overridden. + android::renderscript::property_get("debug.rs.precision", buf, ""); + if (buf[0] != '\0') { + return true; + } + + // Re-compile if debug.rs.forcerecompile is set. + android::renderscript::property_get("debug.rs.forcerecompile", buf, "0"); + if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) { + return true; + } else { + return false; + } +} + +} // anonymous namespace + #endif // RSD_CPU_SCRIPT_H diff --git a/cpu_ref/rsCpuScriptGroup2.cpp b/cpu_ref/rsCpuScriptGroup2.cpp index 11393ff4..d624e623 100644 --- a/cpu_ref/rsCpuScriptGroup2.cpp +++ b/cpu_ref/rsCpuScriptGroup2.cpp @@ -473,8 +473,13 @@ void CpuScriptGroup2Impl::compile(const char* cacheDir) { bool alreadyLoaded = false; std::string cloneName; - mScriptObj = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName, nullptr, - &alreadyLoaded); + const bool useRSDebugContext = + (mCpuRefImpl->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG); + const bool reuse = !is_force_recompile() && !useRSDebugContext; + if (reuse) { + 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. @@ -528,8 +533,11 @@ void CpuScriptGroup2Impl::compile(const char* cacheDir) { // Create and load the shared lib //===--------------------------------------------------------------------===// + std::string SOPath; + if (!SharedLibraryUtils::createSharedLibrary( - getCpuRefImpl()->getContext()->getDriverName(), cacheDir, resName)) { + getCpuRefImpl()->getContext()->getDriverName(), cacheDir, resName, + reuse, &SOPath)) { ALOGE("Failed to link object file '%s'", resName); unlink(objFilePath.c_str()); return; @@ -537,7 +545,11 @@ void CpuScriptGroup2Impl::compile(const char* cacheDir) { unlink(objFilePath.c_str()); - mScriptObj = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName); + if (reuse) { + mScriptObj = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName); + } else { + mScriptObj = SharedLibraryUtils::loadAndDeleteSharedLibrary(SOPath.c_str()); + } if (mScriptObj == nullptr) { ALOGE("Unable to load '%s'", resName); return; |