aboutsummaryrefslogtreecommitdiffstats
path: root/src/android.c
diff options
context:
space:
mode:
authorPo Lu2023-06-10 16:10:46 +0800
committerPo Lu2023-06-10 16:10:46 +0800
commit41acfaea1c4c947e26031917bf21c98ec047b32c (patch)
tree46eb99cf819ed3a6f9e4da6a253f725eb13c8cfb /src/android.c
parenta0b8f60ce79f93f37242a20d7b9a3e3b7ddc46a1 (diff)
downloademacs-41acfaea1c4c947e26031917bf21c98ec047b32c.tar.gz
emacs-41acfaea1c4c947e26031917bf21c98ec047b32c.zip
Update Android port
* src/android.c (android_select, android_check_query) (android_check_query_urgent, android_answer_query) (android_answer_query_spin, android_begin_query, android_end_query) (android_run_in_emacs_thread): Use finer grained memory synchronization semantics. * src/androidterm.c (android_get_selection): Use the current selection, not its value at the time of the last redisplay. * src/keyboard.c (handle_input_available_signal): Place memory barrier.
Diffstat (limited to 'src/android.c')
-rw-r--r--src/android.c108
1 files changed, 62 insertions, 46 deletions
diff --git a/src/android.c b/src/android.c
index cfc777c3caa..b88d072e303 100644
--- a/src/android.c
+++ b/src/android.c
@@ -717,7 +717,7 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds,
717 /* Since Emacs is reading keyboard input again, signify that queries 717 /* Since Emacs is reading keyboard input again, signify that queries
718 from input methods are no longer ``urgent''. */ 718 from input methods are no longer ``urgent''. */
719 719
720 __atomic_clear (&android_urgent_query, __ATOMIC_SEQ_CST); 720 __atomic_clear (&android_urgent_query, __ATOMIC_RELEASE);
721 721
722 /* Check for and run anything the UI thread wants to run on the main 722 /* Check for and run anything the UI thread wants to run on the main
723 thread. */ 723 thread. */
@@ -7072,13 +7072,22 @@ static void *android_query_context;
7072 the UI thread, but is not possible the other way around. 7072 the UI thread, but is not possible the other way around.
7073 7073
7074 To avoid such deadlocks, an atomic counter is provided. This 7074 To avoid such deadlocks, an atomic counter is provided. This
7075 counter is incremented every time a query starts, and is set to 7075 counter is set to two every time a query starts from the main
7076 zerp every time one ends. If the UI thread tries to make a query 7076 thread, and is set to zero every time one ends. If the UI thread
7077 and sees that the counter is non-zero, it simply returns so that 7077 tries to make a query and sees that the counter is two, it simply
7078 its event loop can proceed to perform and respond to the query. If 7078 returns so that its event loop can proceed to perform and respond
7079 the Emacs thread sees the same thing, then it stops to service all 7079 to the query. If the Emacs thread sees that the counter is one,
7080 queries being made by the input method, then proceeds to make its 7080 then it stops to service all queries being made by the input
7081 query. */ 7081 method, then proceeds to make its query with the counter set to
7082 2.
7083
7084 The memory synchronization is simple: all writes to
7085 `android_query_context' and `android_query_function' are depended
7086 on by writes to the atomic counter. Loads of the new value from
7087 the counter are then guaranteed to make those writes visible. The
7088 separate flag `android_urgent_query' does not depend on anything
7089 itself; however, the input signal handler executes a memory fence
7090 to ensure that all query related writes become visible. */
7082 7091
7083/* Run any function that the UI thread has asked to run, and then 7092/* Run any function that the UI thread has asked to run, and then
7084 signal its completion. */ 7093 signal its completion. */
@@ -7089,12 +7098,12 @@ android_check_query (void)
7089 void (*proc) (void *); 7098 void (*proc) (void *);
7090 void *closure; 7099 void *closure;
7091 7100
7092 if (!__atomic_load_n (&android_servicing_query, __ATOMIC_SEQ_CST)) 7101 if (!__atomic_load_n (&android_servicing_query, __ATOMIC_ACQUIRE))
7093 return; 7102 return;
7094 7103
7095 /* First, load the procedure and closure. */ 7104 /* First, load the procedure and closure. */
7096 __atomic_load (&android_query_context, &closure, __ATOMIC_SEQ_CST); 7105 closure = android_query_context;
7097 __atomic_load (&android_query_function, &proc, __ATOMIC_SEQ_CST); 7106 proc = android_query_function;
7098 7107
7099 if (!proc) 7108 if (!proc)
7100 return; 7109 return;
@@ -7102,10 +7111,10 @@ android_check_query (void)
7102 proc (closure); 7111 proc (closure);
7103 7112
7104 /* Finish the query. */ 7113 /* Finish the query. */
7105 __atomic_store_n (&android_query_context, NULL, __ATOMIC_SEQ_CST); 7114 android_query_context = NULL;
7106 __atomic_store_n (&android_query_function, NULL, __ATOMIC_SEQ_CST); 7115 android_query_function = NULL;
7107 __atomic_store_n (&android_servicing_query, 0, __ATOMIC_SEQ_CST); 7116 __atomic_store_n (&android_servicing_query, 0, __ATOMIC_RELEASE);
7108 __atomic_clear (&android_urgent_query, __ATOMIC_SEQ_CST); 7117 __atomic_clear (&android_urgent_query, __ATOMIC_RELEASE);
7109 7118
7110 /* Signal completion. */ 7119 /* Signal completion. */
7111 sem_post (&android_query_sem); 7120 sem_post (&android_query_sem);
@@ -7124,18 +7133,18 @@ android_check_query_urgent (void)
7124 void (*proc) (void *); 7133 void (*proc) (void *);
7125 void *closure; 7134 void *closure;
7126 7135
7127 if (!__atomic_load_n (&android_urgent_query, __ATOMIC_SEQ_CST)) 7136 if (!__atomic_load_n (&android_urgent_query, __ATOMIC_ACQUIRE))
7128 return; 7137 return;
7129 7138
7130 __android_log_print (ANDROID_LOG_VERBOSE, __func__, 7139 __android_log_print (ANDROID_LOG_VERBOSE, __func__,
7131 "Responding to urgent query..."); 7140 "Responding to urgent query...");
7132 7141
7133 if (!__atomic_load_n (&android_servicing_query, __ATOMIC_SEQ_CST)) 7142 if (!__atomic_load_n (&android_servicing_query, __ATOMIC_ACQUIRE))
7134 return; 7143 return;
7135 7144
7136 /* First, load the procedure and closure. */ 7145 /* First, load the procedure and closure. */
7137 __atomic_load (&android_query_context, &closure, __ATOMIC_SEQ_CST); 7146 closure = android_query_context;
7138 __atomic_load (&android_query_function, &proc, __ATOMIC_SEQ_CST); 7147 proc = android_query_function;
7139 7148
7140 if (!proc) 7149 if (!proc)
7141 return; 7150 return;
@@ -7145,9 +7154,9 @@ android_check_query_urgent (void)
7145 /* Finish the query. Don't clear `android_urgent_query'; instead, 7154 /* Finish the query. Don't clear `android_urgent_query'; instead,
7146 do that the next time Emacs enters the keyboard loop. */ 7155 do that the next time Emacs enters the keyboard loop. */
7147 7156
7148 __atomic_store_n (&android_query_context, NULL, __ATOMIC_SEQ_CST); 7157 android_query_context = NULL;
7149 __atomic_store_n (&android_query_function, NULL, __ATOMIC_SEQ_CST); 7158 android_query_function = NULL;
7150 __atomic_store_n (&android_servicing_query, 0, __ATOMIC_SEQ_CST); 7159 __atomic_store_n (&android_servicing_query, 0, __ATOMIC_RELEASE);
7151 7160
7152 /* Signal completion. */ 7161 /* Signal completion. */
7153 sem_post (&android_query_sem); 7162 sem_post (&android_query_sem);
@@ -7163,12 +7172,13 @@ android_answer_query (void)
7163 void (*proc) (void *); 7172 void (*proc) (void *);
7164 void *closure; 7173 void *closure;
7165 7174
7166 eassert (__atomic_load_n (&android_servicing_query, __ATOMIC_SEQ_CST) 7175 eassert (__atomic_load_n (&android_servicing_query,
7176 __ATOMIC_ACQUIRE)
7167 == 1); 7177 == 1);
7168 7178
7169 /* First, load the procedure and closure. */ 7179 /* First, load the procedure and closure. */
7170 __atomic_load (&android_query_context, &closure, __ATOMIC_SEQ_CST); 7180 closure = android_query_context;
7171 __atomic_load (&android_query_function, &proc, __ATOMIC_SEQ_CST); 7181 proc = android_query_function;
7172 7182
7173 if (!proc) 7183 if (!proc)
7174 return; 7184 return;
@@ -7176,9 +7186,9 @@ android_answer_query (void)
7176 proc (closure); 7186 proc (closure);
7177 7187
7178 /* Finish the query. */ 7188 /* Finish the query. */
7179 __atomic_store_n (&android_query_context, NULL, __ATOMIC_SEQ_CST); 7189 android_query_context = NULL;
7180 __atomic_store_n (&android_query_function, NULL, __ATOMIC_SEQ_CST); 7190 android_query_function = NULL;
7181 __atomic_clear (&android_urgent_query, __ATOMIC_SEQ_CST); 7191 __atomic_clear (&android_urgent_query, __ATOMIC_RELEASE);
7182 7192
7183 /* Signal completion. */ 7193 /* Signal completion. */
7184 sem_post (&android_query_sem); 7194 sem_post (&android_query_sem);
@@ -7193,7 +7203,7 @@ android_answer_query_spin (void)
7193 int n; 7203 int n;
7194 7204
7195 while (!(n = __atomic_load_n (&android_servicing_query, 7205 while (!(n = __atomic_load_n (&android_servicing_query,
7196 __ATOMIC_SEQ_CST))) 7206 __ATOMIC_ACQUIRE)))
7197 eassert (!n); 7207 eassert (!n);
7198 7208
7199 /* Note that this function is supposed to be called before 7209 /* Note that this function is supposed to be called before
@@ -7212,11 +7222,11 @@ android_begin_query (void)
7212{ 7222{
7213 char old; 7223 char old;
7214 7224
7215 /* Load the previous value of `android_servicing_query' and upgrade 7225 /* Load the previous value of `android_servicing_query' and then set
7216 it to 2. */ 7226 it to 2. */
7217 7227
7218 old = __atomic_exchange_n (&android_servicing_query, 7228 old = __atomic_exchange_n (&android_servicing_query,
7219 2, __ATOMIC_SEQ_CST); 7229 2, __ATOMIC_ACQ_REL);
7220 7230
7221 /* See if a query was previously in progress. */ 7231 /* See if a query was previously in progress. */
7222 if (old == 1) 7232 if (old == 1)
@@ -7235,8 +7245,8 @@ android_begin_query (void)
7235static void 7245static void
7236android_end_query (void) 7246android_end_query (void)
7237{ 7247{
7238 __atomic_store_n (&android_servicing_query, 0, __ATOMIC_SEQ_CST); 7248 __atomic_store_n (&android_servicing_query, 0, __ATOMIC_RELEASE);
7239 __atomic_clear (&android_urgent_query, __ATOMIC_SEQ_CST); 7249 __atomic_clear (&android_urgent_query, __ATOMIC_RELEASE);
7240} 7250}
7241 7251
7242/* Synchronously ask the Emacs thread to run the specified PROC with 7252/* Synchronously ask the Emacs thread to run the specified PROC with
@@ -7264,8 +7274,8 @@ android_run_in_emacs_thread (void (*proc) (void *), void *closure)
7264 event.xaction.action = 0; 7274 event.xaction.action = 0;
7265 7275
7266 /* Set android_query_function and android_query_context. */ 7276 /* Set android_query_function and android_query_context. */
7267 __atomic_store_n (&android_query_context, closure, __ATOMIC_SEQ_CST); 7277 android_query_context = closure;
7268 __atomic_store_n (&android_query_function, proc, __ATOMIC_SEQ_CST); 7278 android_query_function = proc;
7269 7279
7270 /* Don't allow deadlocks to happen; make sure the Emacs thread is 7280 /* Don't allow deadlocks to happen; make sure the Emacs thread is
7271 not waiting for something to be done (in that case, 7281 not waiting for something to be done (in that case,
@@ -7273,13 +7283,15 @@ android_run_in_emacs_thread (void (*proc) (void *), void *closure)
7273 7283
7274 old = 0; 7284 old = 0;
7275 if (!__atomic_compare_exchange_n (&android_servicing_query, &old, 7285 if (!__atomic_compare_exchange_n (&android_servicing_query, &old,
7276 1, false, __ATOMIC_SEQ_CST, 7286 1, false, __ATOMIC_ACQ_REL,
7277 __ATOMIC_SEQ_CST)) 7287 __ATOMIC_ACQUIRE))
7278 { 7288 {
7279 __atomic_store_n (&android_query_context, NULL, 7289 android_query_context = NULL;
7280 __ATOMIC_SEQ_CST); 7290 android_query_function = NULL;
7281 __atomic_store_n (&android_query_function, NULL, 7291
7282 __ATOMIC_SEQ_CST); 7292 /* The two variables above may still be non-NULL from the POV of
7293 the main thread, as no happens-before constraint is placed on
7294 those stores wrt a future load from `android_servicing_query'. */
7283 7295
7284 return 1; 7296 return 1;
7285 } 7297 }
@@ -7302,7 +7314,7 @@ android_run_in_emacs_thread (void (*proc) (void *), void *closure)
7302 keyboard loop in between. When that happens, raise SIGIO to 7314 keyboard loop in between. When that happens, raise SIGIO to
7303 continue processing queries as soon as possible. */ 7315 continue processing queries as soon as possible. */
7304 7316
7305 if (__atomic_load_n (&android_urgent_query, __ATOMIC_SEQ_CST)) 7317 if (__atomic_load_n (&android_urgent_query, __ATOMIC_ACQUIRE))
7306 raise (SIGIO); 7318 raise (SIGIO);
7307 7319
7308 again: 7320 again:
@@ -7321,7 +7333,8 @@ android_run_in_emacs_thread (void (*proc) (void *), void *closure)
7321 7333
7322 /* The query timed out. At this point, set 7334 /* The query timed out. At this point, set
7323 `android_urgent_query' to true. */ 7335 `android_urgent_query' to true. */
7324 __atomic_store_n (&android_urgent_query, true, __ATOMIC_SEQ_CST); 7336 __atomic_store_n (&android_urgent_query, true,
7337 __ATOMIC_RELEASE);
7325 7338
7326 /* And raise SIGIO. Now that the query is considered urgent, 7339 /* And raise SIGIO. Now that the query is considered urgent,
7327 the main thread will reply while reading async input. 7340 the main thread will reply while reading async input.
@@ -7331,7 +7344,10 @@ android_run_in_emacs_thread (void (*proc) (void *), void *closure)
7331 inaccurate results taken during command executioon. */ 7344 inaccurate results taken during command executioon. */
7332 raise (SIGIO); 7345 raise (SIGIO);
7333 7346
7334 /* Wait for the query to complete. */ 7347 /* Wait for the query to complete. `android_urgent_query' is
7348 only cleared by either `android_select' or
7349 `android_check_query', so there's no need to worry about the
7350 flag being cleared before the query is processed. */
7335 while (sem_wait (&android_query_sem) < 0) 7351 while (sem_wait (&android_query_sem) < 0)
7336 ;; 7352 ;;
7337 } 7353 }
@@ -7341,9 +7357,9 @@ android_run_in_emacs_thread (void (*proc) (void *), void *closure)
7341 query. */ 7357 query. */
7342 7358
7343 eassert (!__atomic_load_n (&android_servicing_query, 7359 eassert (!__atomic_load_n (&android_servicing_query,
7344 __ATOMIC_SEQ_CST) 7360 __ATOMIC_ACQUIRE)
7345 || (__atomic_load_n (&android_servicing_query, 7361 || (__atomic_load_n (&android_servicing_query,
7346 __ATOMIC_SEQ_CST) == 2)); 7362 __ATOMIC_ACQUIRE) == 2));
7347 7363
7348 return 0; 7364 return 0;
7349} 7365}