diff options
| author | Po Lu | 2024-02-06 17:52:33 +0800 |
|---|---|---|
| committer | Po Lu | 2024-02-06 17:53:23 +0800 |
| commit | 42db7292c3e05920bc9f2fa5c3478eb2ba835c5c (patch) | |
| tree | 7683bc7a9595f48734b43e5ee6c0eac660fdc39a /src/thread.c | |
| parent | 0d2b7120783255fbb0f8e98717573c35425f4df6 (diff) | |
| download | emacs-42db7292c3e05920bc9f2fa5c3478eb2ba835c5c.tar.gz emacs-42db7292c3e05920bc9f2fa5c3478eb2ba835c5c.zip | |
Implement Lisp threading on Android
Much like the NS port, only the main thread receives input from
the user interface, which is fortunately not a major problem for
packages such as lsp-mode that create Lisp threads.
* configure.ac: Enable with_threads under Android.
* src/android.c (android_init_events): Set `main_thread_id' to
the ID of the main thread.
(setEmacsParams): Set new global variable `android_jvm' to the
JVM object, for the purpose of attaching Lisp threads to the
JVM.
(android_select): [THREADS_ENABLED]: If the caller isn't the
main thread, resort to pselect. Don't check query before select
returns.
(android_check_query): Export.
* src/android.h (_ANDROID_H_): Define new macro and update
prototypes.
* src/process.c (android_select_wrapper): New function.
(wait_reading_process_output): If THREADS_ENABLED, call
thread_select through the Android select wrapper.
* src/thread.c (post_acquire_global_lock): Call
android_check_query; replace android_java_env with the incoming
Lisp thread's.
(run_thread): Attach and detach the thread created to the JVM.
(init_threads): Set the main thread's JNI environment object.
* src/thread.h (struct thread_state) <java_env>: New field.
Diffstat (limited to 'src/thread.c')
| -rw-r--r-- | src/thread.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/thread.c b/src/thread.c index 040ca39511e..2f5d7a08838 100644 --- a/src/thread.c +++ b/src/thread.c | |||
| @@ -106,6 +106,12 @@ post_acquire_global_lock (struct thread_state *self) | |||
| 106 | { | 106 | { |
| 107 | struct thread_state *prev_thread = current_thread; | 107 | struct thread_state *prev_thread = current_thread; |
| 108 | 108 | ||
| 109 | /* Switch the JNI interface pointer to the environment assigned to the | ||
| 110 | current thread. */ | ||
| 111 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 112 | android_java_env = self->java_env; | ||
| 113 | #endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ | ||
| 114 | |||
| 109 | /* Do this early on, so that code below could signal errors (e.g., | 115 | /* Do this early on, so that code below could signal errors (e.g., |
| 110 | unbind_for_thread_switch might) correctly, because we are already | 116 | unbind_for_thread_switch might) correctly, because we are already |
| 111 | running in the context of the thread pointed by SELF. */ | 117 | running in the context of the thread pointed by SELF. */ |
| @@ -126,6 +132,12 @@ post_acquire_global_lock (struct thread_state *self) | |||
| 126 | set_buffer_internal_2 (current_buffer); | 132 | set_buffer_internal_2 (current_buffer); |
| 127 | } | 133 | } |
| 128 | 134 | ||
| 135 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 136 | /* This step is performed in android_select when built without | ||
| 137 | threads. */ | ||
| 138 | android_check_query (); | ||
| 139 | #endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ | ||
| 140 | |||
| 129 | /* We could have been signaled while waiting to grab the global lock | 141 | /* We could have been signaled while waiting to grab the global lock |
| 130 | for the first time since this thread was created, in which case | 142 | for the first time since this thread was created, in which case |
| 131 | we didn't yet have the opportunity to set up the handlers. Delay | 143 | we didn't yet have the opportunity to set up the handlers. Delay |
| @@ -756,6 +768,11 @@ run_thread (void *state) | |||
| 756 | 768 | ||
| 757 | struct thread_state *self = state; | 769 | struct thread_state *self = state; |
| 758 | struct thread_state **iter; | 770 | struct thread_state **iter; |
| 771 | #ifdef THREADS_ENABLED | ||
| 772 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 773 | jint rc; | ||
| 774 | #endif /* #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ | ||
| 775 | #endif /* THREADS_ENABLED */ | ||
| 759 | 776 | ||
| 760 | #ifdef HAVE_NS | 777 | #ifdef HAVE_NS |
| 761 | /* Allocate an autorelease pool in case this thread calls any | 778 | /* Allocate an autorelease pool in case this thread calls any |
| @@ -766,6 +783,16 @@ run_thread (void *state) | |||
| 766 | void *pool = ns_alloc_autorelease_pool (); | 783 | void *pool = ns_alloc_autorelease_pool (); |
| 767 | #endif | 784 | #endif |
| 768 | 785 | ||
| 786 | #ifdef THREADS_ENABLED | ||
| 787 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 788 | rc | ||
| 789 | = (*android_jvm)->AttachCurrentThread (android_jvm, &self->java_env, | ||
| 790 | NULL); | ||
| 791 | if (rc != JNI_OK) | ||
| 792 | emacs_abort (); | ||
| 793 | #endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ | ||
| 794 | #endif /* THREADS_ENABLED */ | ||
| 795 | |||
| 769 | self->m_stack_bottom = self->stack_top = &stack_pos.c; | 796 | self->m_stack_bottom = self->stack_top = &stack_pos.c; |
| 770 | self->thread_id = sys_thread_self (); | 797 | self->thread_id = sys_thread_self (); |
| 771 | 798 | ||
| @@ -812,6 +839,14 @@ run_thread (void *state) | |||
| 812 | ns_release_autorelease_pool (pool); | 839 | ns_release_autorelease_pool (pool); |
| 813 | #endif | 840 | #endif |
| 814 | 841 | ||
| 842 | #ifdef THREADS_ENABLED | ||
| 843 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 844 | rc = (*android_jvm)->DetachCurrentThread (android_jvm); | ||
| 845 | if (rc != JNI_OK) | ||
| 846 | emacs_abort (); | ||
| 847 | #endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ | ||
| 848 | #endif /* THREADS_ENABLED */ | ||
| 849 | |||
| 815 | /* Unlink this thread from the list of all threads. Note that we | 850 | /* Unlink this thread from the list of all threads. Note that we |
| 816 | have to do this very late, after broadcasting our death. | 851 | have to do this very late, after broadcasting our death. |
| 817 | Otherwise the GC may decide to reap the thread_state object, | 852 | Otherwise the GC may decide to reap the thread_state object, |
| @@ -1131,6 +1166,10 @@ init_threads (void) | |||
| 1131 | sys_mutex_init (&global_lock); | 1166 | sys_mutex_init (&global_lock); |
| 1132 | sys_mutex_lock (&global_lock); | 1167 | sys_mutex_lock (&global_lock); |
| 1133 | current_thread = &main_thread.s; | 1168 | current_thread = &main_thread.s; |
| 1169 | #if defined HAVE_ANDROID && !defined ANDROID_STUBIFY | ||
| 1170 | current_thread->java_env = android_java_env; | ||
| 1171 | #endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */ | ||
| 1172 | |||
| 1134 | main_thread.s.thread_id = sys_thread_self (); | 1173 | main_thread.s.thread_id = sys_thread_self (); |
| 1135 | init_bc_thread (&main_thread.s.bc); | 1174 | init_bc_thread (&main_thread.s.bc); |
| 1136 | } | 1175 | } |