summaryrefslogtreecommitdiff
path: root/retro_emu_thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'retro_emu_thread.c')
-rw-r--r--retro_emu_thread.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/retro_emu_thread.c b/retro_emu_thread.c
new file mode 100644
index 0000000..2df7db7
--- /dev/null
+++ b/retro_emu_thread.c
@@ -0,0 +1,175 @@
+// This is copyrighted software. More information is at the end of this file.
+#include "retro_emu_thread.h"
+
+#include <pthread.h>
+
+static pthread_t main_thread;
+static pthread_t emu_thread;
+static pthread_mutex_t emu_mutex;
+static pthread_mutex_t main_mutex;
+static pthread_cond_t emu_cv;
+static pthread_cond_t main_cv;
+static bool emu_keep_waiting = true;
+static bool main_keep_waiting = true;
+static bool emu_has_exited = false;
+static bool emu_thread_canceled = false;
+static bool emu_thread_initialized = false;
+
+static void* retro_run_emulator(void *args)
+{
+ char *args_str = (char *)args;
+ bool dynarec = (*args_str++ == 1) ? true : false;
+ u32 cycles = strtol(args_str, NULL, 10);
+
+ emu_has_exited = false;
+ emu_thread_canceled = false;
+
+#if defined(HAVE_DYNAREC)
+ if (dynarec)
+ execute_arm_translate(cycles);
+#endif
+ execute_arm(cycles);
+
+ emu_has_exited = true;
+ return NULL;
+}
+
+static void retro_switch_to_emu_thread()
+{
+ pthread_mutex_lock(&emu_mutex);
+ emu_keep_waiting = false;
+ pthread_mutex_unlock(&emu_mutex);
+ pthread_mutex_lock(&main_mutex);
+ pthread_cond_signal(&emu_cv);
+
+ main_keep_waiting = true;
+ while (main_keep_waiting)
+ {
+ pthread_cond_wait(&main_cv, &main_mutex);
+ }
+ pthread_mutex_unlock(&main_mutex);
+}
+
+static void retro_switch_to_main_thread()
+{
+ pthread_mutex_lock(&main_mutex);
+ main_keep_waiting = false;
+ pthread_mutex_unlock(&main_mutex);
+ pthread_mutex_lock(&emu_mutex);
+ pthread_cond_signal(&main_cv);
+
+ emu_keep_waiting = true;
+ while (emu_keep_waiting)
+ {
+ pthread_cond_wait(&emu_cv, &emu_mutex);
+ }
+ pthread_mutex_unlock(&emu_mutex);
+}
+
+void retro_switch_thread()
+{
+ if (pthread_self() == main_thread)
+ retro_switch_to_emu_thread();
+ else
+ retro_switch_to_main_thread();
+}
+
+bool retro_init_emu_thread(bool dynarec, u32 cycles)
+{
+ char args[256];
+ args[0] = '\0';
+
+ if (emu_thread_initialized)
+ return true;
+
+ /* Keep this very simple:
+ * - First character: dynarec, 0/1
+ * - Remaining characters: cycles */
+ snprintf(args, sizeof(args), " %u", cycles);
+ args[0] = dynarec ? 1 : 0;
+
+ main_thread = pthread_self();
+ if (pthread_mutex_init(&main_mutex, NULL))
+ goto main_mutex_error;
+ if (pthread_mutex_init(&emu_mutex, NULL))
+ goto emu_mutex_error;
+ if (pthread_cond_init(&main_cv, NULL))
+ goto main_cv_error;
+ if (pthread_cond_init(&emu_cv, NULL))
+ goto emu_cv_error;
+ if (pthread_create(&emu_thread, NULL, retro_run_emulator, args))
+ goto emu_thread_error;
+
+ emu_thread_initialized = true;
+ return true;
+
+emu_thread_error:
+ pthread_cond_destroy(&emu_cv);
+emu_cv_error:
+ pthread_cond_destroy(&main_cv);
+main_cv_error:
+ pthread_mutex_destroy(&emu_mutex);
+emu_mutex_error:
+ pthread_mutex_destroy(&main_mutex);
+main_mutex_error:
+ return false;
+}
+
+void retro_deinit_emu_thread()
+{
+ if (!emu_thread_initialized)
+ return;
+
+ pthread_mutex_destroy(&main_mutex);
+ pthread_mutex_destroy(&emu_mutex);
+ pthread_cond_destroy(&main_cv);
+ pthread_cond_destroy(&emu_cv);
+ emu_thread_initialized = false;
+}
+
+bool retro_is_emu_thread_initialized()
+{
+ return emu_thread_initialized;
+}
+
+void retro_join_emu_thread()
+{
+ static bool is_joined = false;
+ if (is_joined)
+ return;
+
+ pthread_join(emu_thread, NULL);
+ is_joined = true;
+}
+
+void retro_cancel_emu_thread()
+{
+ if (emu_thread_canceled)
+ return;
+
+ pthread_cancel(emu_thread);
+ emu_thread_canceled = true;
+}
+
+bool retro_emu_thread_exited()
+{
+ return emu_has_exited;
+}
+
+/*
+
+Copyright (C) 2020 Nikos Chantziaras <realnc@gmail.com>
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <https://www.gnu.org/licenses/>.
+
+*/