From 94f2107df113982d58cda32260c8ff73c442b829 Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 21 Apr 2020 00:05:12 +0200 Subject: [PATCH] Acquire global mutex to obtain mutex for java obj update stress test jni92, add option useSharedEngines --- src/basic_api.cc | 135 ++++++++++++++---- ...oundation_pEp_jniadapter_AbstractEngine.cc | 105 +++++++++----- src/gen_cpp_Engine.ysl2 | 9 +- src/jniutils.cc | 3 +- .../pEp/jniadapter/test/jni92/TestMain.java | 36 +++-- .../pEp/jniadapter/test/utils/TestUtils.java | 20 ++- 6 files changed, 226 insertions(+), 82 deletions(-) diff --git a/src/basic_api.cc b/src/basic_api.cc index f776eab..d16553b 100644 --- a/src/basic_api.cc +++ b/src/basic_api.cc @@ -19,8 +19,13 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine_trustwords( jobject ident ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pEp_identity *_ident = to_identity(env, ident); char *words; @@ -59,8 +64,13 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine_myself( jobject ident ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pEp_identity *_ident = to_identity(env, ident); @@ -80,8 +90,13 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine_updateIdentity( jobject ident ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pEp_identity *_ident = to_identity(env, ident); @@ -97,8 +112,13 @@ JNIEXPORT jobject JNICALL Java_foundation_pEp_jniadapter_Engine_setOwnKey( jbyteArray fpr ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pEp_identity *_ident = to_identity(env, ident); char *_fpr = to_string(env, fpr); @@ -120,8 +140,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_keyMistrusted( jobject ident ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pEp_identity *_ident = to_identity(env, ident); @@ -146,8 +171,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_keyResetTrust( jobject ident ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pEp_identity *_ident = to_identity(env, ident); @@ -172,8 +202,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_trustPersonalKey( jobject ident ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pEp_identity *_ident = to_identity(env, ident); @@ -198,8 +233,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_trustOwnKey( jobject ident ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pEp_identity *_ident = to_identity(env, ident); @@ -217,8 +257,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_importKey( jbyteArray key ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); size_t _size = (size_t) env->GetArrayLength(key); char *_key = (char *) env->GetByteArrayElements(key, NULL); @@ -243,8 +288,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_config_1passive_1mo jboolean enable ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); ::config_passive_mode(session(), (bool)enable); } @@ -256,8 +306,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_config_1unencrypted jboolean enable ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); ::config_unencrypted_subject(session(), (bool)enable); } @@ -268,8 +323,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_blacklist_1add( jbyteArray fpr ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); char *_fpr = to_string(env, fpr); @@ -292,8 +352,13 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_Engine_blacklist_1delete( jbyteArray fpr ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); char *_fpr = to_string(env, fpr); @@ -316,8 +381,13 @@ JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_Engine_blacklist_1is_1 jbyteArray fpr ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); char *_fpr = to_string(env, fpr); bool _listed = 0; @@ -343,8 +413,13 @@ JNIEXPORT jbyteArray JNICALL Java_foundation_pEp_jniadapter_Engine_getCrashdumpL jint maxlines ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); int _maxlines = (int) maxlines; char *_logdata; diff --git a/src/foundation_pEp_jniadapter_AbstractEngine.cc b/src/foundation_pEp_jniadapter_AbstractEngine.cc index 0ed33d8..40d4e03 100644 --- a/src/foundation_pEp_jniadapter_AbstractEngine.cc +++ b/src/foundation_pEp_jniadapter_AbstractEngine.cc @@ -172,54 +172,64 @@ using namespace pEp; JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_init( JNIEnv *env, - jobject me + jobject obj ) { - pEpLog("called"); std::lock_guard l(global_mutex); // global mutex for write access to + pEpLog("called"); if (first) { pEpLog("first Engine instance"); first = false; env->GetJavaVM(&jvm); jni_init(); - objj = env->NewGlobalRef(me); + objj = env->NewGlobalRef(obj); Adapter::_messageToSend = messageToSend; } - create_engine_java_object_mutex(env, me); // Create a mutex per java object + create_engine_java_object_mutex(env, obj); // Create a mutex per java object Adapter::session(); } JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_release( JNIEnv *env, - jobject me + jobject obj ) { - pEpLog("called"); std::lock_guard l(global_mutex); // global mutex for write access to - release_engine_java_object_mutex(env, me); + pEpLog("called"); + release_engine_java_object_mutex(env, obj); Adapter::session(pEp::Adapter::release); } JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getVersion( JNIEnv *env, - jobject me + jobject obj ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, me)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); return env->NewStringUTF(::get_engine_version()); } JNIEXPORT jstring JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_getProtocolVersion( JNIEnv *env, - jobject me + jobject obj ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, me)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); return env->NewStringUTF(::get_protocol_version()); } @@ -263,11 +273,16 @@ static void *keyserver_thread_routine(void *arg) JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startKeyserverLookup( JNIEnv *env, - jobject me + jobject obj ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, me)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pthread_t *thread = nullptr; locked_queue< pEp_identity * > *queue = nullptr; @@ -284,16 +299,16 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startKeyser return; } - thread = (pthread_t *) env->GetLongField(me, thread_handle); + thread = (pthread_t *) env->GetLongField(obj, thread_handle); if (thread) return; thread = (pthread_t *) calloc(1, sizeof(pthread_t)); assert(thread); - env->SetLongField(me, thread_handle, (jlong) thread); + env->SetLongField(obj, thread_handle, (jlong) thread); queue = new locked_queue< pEp_identity * >(); - env->SetLongField(me, queue_handle, (jlong) queue); + env->SetLongField(obj, queue_handle, (jlong) queue); register_examine_function(Adapter::session(), examine_identity, (void *) queue); @@ -302,11 +317,16 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startKeyser JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopKeyserverLookup( JNIEnv *env, - jobject me + jobject obj ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, me)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pthread_t *thread = nullptr; locked_queue< pEp_identity * > *queue = nullptr; @@ -323,14 +343,14 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopKeyserv return; } - thread = (pthread_t *) env->GetLongField(me, thread_handle); + thread = (pthread_t *) env->GetLongField(obj, thread_handle); if (!thread) return; - queue = (locked_queue< pEp_identity * > *) env->GetLongField(me, queue_handle); + queue = (locked_queue< pEp_identity * > *) env->GetLongField(obj, queue_handle); - env->SetLongField(me, queue_handle, (jlong) 0); - env->SetLongField(me, thread_handle, (jlong) 0); + env->SetLongField(obj, queue_handle, (jlong) 0); + env->SetLongField(obj, thread_handle, (jlong) 0); register_examine_function(Adapter::session(), nullptr, nullptr); @@ -341,11 +361,16 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopKeyserv JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startSync( JNIEnv *env, - jobject me + jobject obj ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, me)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); pEpLog("######## starting sync"); try { @@ -359,22 +384,32 @@ JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_startSync( JNIEXPORT void JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_stopSync( JNIEnv *env, - jobject me + jobject obj ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, me)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); Adapter::shutdown(); } JNIEXPORT jboolean JNICALL Java_foundation_pEp_jniadapter_AbstractEngine_isSyncRunning( JNIEnv *env, - jobject me + jobject obj ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, me)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); return (jboolean) Adapter::is_sync_running(); } diff --git a/src/gen_cpp_Engine.ysl2 b/src/gen_cpp_Engine.ysl2 index 853d4b0..3fb0e1c 100644 --- a/src/gen_cpp_Engine.ysl2 +++ b/src/gen_cpp_Engine.ysl2 @@ -47,8 +47,13 @@ tstylesheet { jobject obj`apply "parm[in|inout]", mode=sig` ) { - pEpLog("called with lock_guard"); - std::lock_guard l(*get_engine_java_object_mutex(env, obj)); + std::mutex *mutex_local = nullptr; + { + std::lock_guard l(global_mutex); + pEpLog("called with lock_guard"); + mutex_local = get_engine_java_object_mutex(env, obj); + } + std::lock_guard l(*mutex_local); || diff --git a/src/jniutils.cc b/src/jniutils.cc index 0ca7b4d..e4d2820 100644 --- a/src/jniutils.cc +++ b/src/jniutils.cc @@ -21,8 +21,9 @@ namespace pEp { { long engine_obj_id = (long)callLongMethod(env, obj, "getId"); assert(engine_obj_id); + pEpLog("for java object id: " << engine_obj_id); std::mutex *engine_obj_mutex = engine_objid_mutex.at(engine_obj_id); - pEpLog(engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle() << " for java object id: " << engine_obj_id); + pEpLog("found mutex: " << engine_obj_mutex << " with native_handle: " << engine_obj_mutex->native_handle()); assert(engine_obj_mutex); return engine_obj_mutex; } diff --git a/test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java b/test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java index a7b8cd5..a646590 100644 --- a/test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java +++ b/test/java/foundation/pEp/jniadapter/test/jni92/TestMain.java @@ -16,19 +16,23 @@ https://pep.foundation/jira/browse/JNI-81 class TestThread extends Thread { int nrEngines = 1; - TestThread(String threadName, int nrEngines) { + boolean useSharedEngines = false; + TestThread(String threadName, int nrEngines, boolean useSharedEngines) { Thread.currentThread().setName(threadName); this.nrEngines = nrEngines; + this.useSharedEngines = useSharedEngines; } public void run() { TestUtils.logH1( "Thread Starting"); - TestMain.TestMainRun(nrEngines); + TestMain.TestMainRun(nrEngines, useSharedEngines); } } class TestMain { + static Vector sharedEngines; + public static Engine createNewEngine() throws pEpException { Engine e; TestUtils.logH2("Creating new Engine"); @@ -52,8 +56,7 @@ class TestMain { }); } - public static void TestMainRun(int nrEngines) { - Vector engineVector = TestMain.createEngines(nrEngines); + public static void TestMainRun(int nrEngines, boolean useSharedEngines) { Consumer c = (e) -> { Vector v = e.own_identities_retrieve(); @@ -64,27 +67,38 @@ class TestMain { e.getVersion(); e.OpenPGP_list_keyinfo(""); }; - TestMain.engineConsumer(engineVector, c); + + if(useSharedEngines) { + TestMain.engineConsumer(sharedEngines, c); + } else { + Vector threadLocalEngines = TestMain.createEngines(nrEngines); + TestMain.engineConsumer(threadLocalEngines, c); + } } public static void main(String[] args) { TestUtils.logH1("JNI-92 Starting"); - - int nrTestruns = 100; + TestUtils.setLoggingEnabled(false); + int nrTestruns = 1000; boolean multiThreaded = true; - int nrThreads = 200; - int nrEnginesPerThread = 100; + boolean useSharedEngines = true; + int nrThreads = 100; + int nrEnginesPerThread = 1; + + if(useSharedEngines) { + sharedEngines = TestMain.createEngines(nrEnginesPerThread); + } for (int run = 0; run < nrTestruns; run++ ) { TestUtils.logH1("Testrun Nr: " + run); if (!multiThreaded) { // Single Threaded - TestMainRun(nrEnginesPerThread); + TestMainRun(nrEnginesPerThread, useSharedEngines); } else { // Mutli Threaded Vector tts = new Vector(); for (int i = 0; i < nrThreads; i++) { - tts.add(new TestThread("TestThread-" + i, nrEnginesPerThread)); + tts.add(new TestThread("TestThread-" + i, nrEnginesPerThread, useSharedEngines)); } tts.forEach(t -> { diff --git a/test/java/foundation/pEp/jniadapter/test/utils/TestUtils.java b/test/java/foundation/pEp/jniadapter/test/utils/TestUtils.java index 83d7d75..3833b18 100644 --- a/test/java/foundation/pEp/jniadapter/test/utils/TestUtils.java +++ b/test/java/foundation/pEp/jniadapter/test/utils/TestUtils.java @@ -22,10 +22,24 @@ public class TestUtils { return ret; } + // ------------------------ Logging ------------------------ + + private static boolean logEnabled = true; + + public static void setLoggingEnabled(boolean enabled) { + logEnabled = enabled; + } + + public static boolean isLoggingEnabled() { + return logEnabled; + } + public static void log(String msg) { - String threadNameFmt = String.format("%-10s", Thread.currentThread().getName()); - String msgOut = threadNameFmt + ": " + msg; - System.out.println(msgOut); + if(logEnabled) { + String threadNameFmt = String.format("%-10s", Thread.currentThread().getName()); + String msgOut = threadNameFmt + ": " + msg; + System.out.println(msgOut); + } } public static void logH1(String msg) {