diff options
| author | Po Lu | 2023-06-10 16:10:46 +0800 |
|---|---|---|
| committer | Po Lu | 2023-06-10 16:10:46 +0800 |
| commit | 41acfaea1c4c947e26031917bf21c98ec047b32c (patch) | |
| tree | 46eb99cf819ed3a6f9e4da6a253f725eb13c8cfb /src/android.c | |
| parent | a0b8f60ce79f93f37242a20d7b9a3e3b7ddc46a1 (diff) | |
| download | emacs-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.c | 108 |
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) | |||
| 7235 | static void | 7245 | static void |
| 7236 | android_end_query (void) | 7246 | android_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 | } |