summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Ni <yangni@google.com>2017-05-01 15:53:23 -0700
committerYang Ni <yangni@google.com>2017-05-04 13:31:51 -0700
commita845c35880f8434619ac299e8af47aa6a5049e8d (patch)
tree250d3cdcfc62e70c8d49eb07bc61d1864906c2a9
parent8a4dd094d119a49d957bcfc13cd8669a29d3bab6 (diff)
downloadrs-a845c35880f8434619ac299e8af47aa6a5049e8d.tar.gz
Use different .so names in a debug context
Bug: 37670543 Bug: 36006390 Bug: 37679566 Bug: 37636434 In debug context, a script is forced to be recompiled every time it is initialized. To avoid the same .so file being written to by another thread, while it is being loaded and used by one thread, do not save the .so file. Delete it right after loading it. Test: RefocusTest and RSTest (including ScriptGroup2 tests) with debug.rs.debug set to 1 and CTS on Angler Change-Id: If63e3d21e3d9abd007a66e0ec79c9e6f1c9f13a0
-rw-r--r--cpu_ref/rsCpuExecutable.cpp41
-rw-r--r--cpu_ref/rsCpuExecutable.h14
-rw-r--r--cpu_ref/rsCpuScript.cpp38
-rw-r--r--cpu_ref/rsCpuScript.h22
-rw-r--r--cpu_ref/rsCpuScriptGroup2.cpp20
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;