diff options
| author | Po Lu | 2025-02-28 19:49:34 +0800 |
|---|---|---|
| committer | Po Lu | 2025-02-28 19:54:46 +0800 |
| commit | 8df582a46836e312ef3bfc36c8038b5f4a2c0d9b (patch) | |
| tree | 752e9136202a8bfaa81000078a5a15e14d919d3e /src/android.c | |
| parent | 8b9194ae03214dd5169bd84f7d83bbe660dd9f90 (diff) | |
| download | emacs-8df582a46836e312ef3bfc36c8038b5f4a2c0d9b.tar.gz emacs-8df582a46836e312ef3bfc36c8038b5f4a2c0d9b.zip | |
Fully support Lisp threads on Android
* src/android.c (struct android_thread_event_queue): New
structure. Move global pselect arguments, mutexes, and
semaphores, and pipes here.
(struct android_event_queue) <select_mutex, select_thread>:
Remove to the above-named struct.
(android_init_thread_events, android_finalize_thread_events)
(android_get_poll_thread): New functions.
(android_run_select_thread): Accept a set of mutexes and
thread-local data as the first argument, and operate with them
rather than globals.
(android_handle_sigusr1): Rename to
`android_handle_poll_signal'. Set thread-specific cancellation
indicator.
(android_init_events): Properly abort after a fatal condition.
Enable interruptible polling on Android 5.1 and later, not 4.2.
(android_select): Never check for queries here, but in
thread_select, if threads are enabled. Adapt to per-thread
polling threads and only enable interruptible polling on Android
5.1 and later.
(android_before_select): New function.
* src/android.h (android_before_select): New declaration.
* src/thread.c (thread_select): Call `android_before_select'
before the global lock is released.
Diffstat (limited to 'src/android.c')
| -rw-r--r-- | src/android.c | 524 |
1 files changed, 339 insertions, 185 deletions
diff --git a/src/android.c b/src/android.c index 05b593f0f31..15edca94fdf 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -266,57 +266,191 @@ struct android_event_container | |||
| 266 | union android_event event; | 266 | union android_event event; |
| 267 | }; | 267 | }; |
| 268 | 268 | ||
| 269 | struct android_event_queue | 269 | /* Thread-specific component of the Android event queue. */ |
| 270 | { | ||
| 271 | /* Mutex protecting the event queue. */ | ||
| 272 | pthread_mutex_t mutex; | ||
| 273 | 270 | ||
| 271 | struct android_thread_event_queue | ||
| 272 | { | ||
| 274 | /* Mutex protecting the select data. */ | 273 | /* Mutex protecting the select data. */ |
| 275 | pthread_mutex_t select_mutex; | 274 | pthread_mutex_t select_mutex; |
| 276 | 275 | ||
| 277 | /* The thread used to run select. */ | 276 | /* The thread used to run select. */ |
| 278 | pthread_t select_thread; | 277 | pthread_t select_thread; |
| 279 | 278 | ||
| 279 | /* Arguments to pselect used by the select thread. */ | ||
| 280 | fd_set *select_readfds; | ||
| 281 | fd_set *select_writefds; | ||
| 282 | fd_set *select_exceptfds; | ||
| 283 | struct timespec *select_timeout; | ||
| 284 | int select_nfds; | ||
| 285 | |||
| 286 | /* Semaphores posted around invocations of pselect. */ | ||
| 287 | sem_t start_sem; | ||
| 288 | sem_t select_sem; | ||
| 289 | |||
| 290 | /* Value of pselect. */ | ||
| 291 | int select_rc; | ||
| 292 | |||
| 293 | #if __ANDROID_API__ < 21 | ||
| 294 | /* Select self-pipe. */ | ||
| 295 | int select_pipe[2]; | ||
| 296 | #else /* __ANDROID_API__ >= 21 */ | ||
| 297 | /* Whether a signal has been received to cancel pselect in this | ||
| 298 | thread. */ | ||
| 299 | volatile sig_atomic_t cancel_signal_received; | ||
| 300 | #endif /* __ANDROID_API__ >= 21 */ | ||
| 301 | |||
| 302 | /* Whether this thread must exit. */ | ||
| 303 | int canceled; | ||
| 304 | }; | ||
| 305 | |||
| 306 | #if __ANDROID_API__ >= 21 | ||
| 307 | #define SELECT_SIGNAL SIGUSR1 | ||
| 308 | #endif /* __ANDROID_API__ >= 21 */ | ||
| 309 | |||
| 310 | struct android_event_queue | ||
| 311 | { | ||
| 312 | /* Mutex protecting the event queue. */ | ||
| 313 | pthread_mutex_t mutex; | ||
| 314 | |||
| 280 | /* Condition variables for the reading side. */ | 315 | /* Condition variables for the reading side. */ |
| 281 | pthread_cond_t read_var; | 316 | pthread_cond_t read_var; |
| 282 | 317 | ||
| 283 | /* The number of events in the queue. If this is greater than 1024, | ||
| 284 | writing will block. */ | ||
| 285 | int num_events; | ||
| 286 | |||
| 287 | /* Circular queue of events. */ | 318 | /* Circular queue of events. */ |
| 288 | struct android_event_container events; | 319 | struct android_event_container events; |
| 289 | }; | ||
| 290 | 320 | ||
| 291 | /* Arguments to pselect used by the select thread. */ | 321 | #ifndef THREADS_ENABLED |
| 292 | static int android_pselect_nfds; | 322 | /* If threads are disabled, the thread-specific component of the main |
| 293 | static fd_set *android_pselect_readfds; | 323 | and only thread. */ |
| 294 | static fd_set *android_pselect_writefds; | 324 | struct android_thread_event_queue thread; |
| 295 | static fd_set *android_pselect_exceptfds; | 325 | #endif /* !THREADS_ENABLED */ |
| 296 | static struct timespec *android_pselect_timeout; | ||
| 297 | 326 | ||
| 298 | /* Value of pselect. */ | 327 | /* The number of events in the queue. */ |
| 299 | static int android_pselect_rc; | 328 | int num_events; |
| 329 | }; | ||
| 300 | 330 | ||
| 301 | /* The global event queue. */ | 331 | /* The global event queue. */ |
| 302 | static struct android_event_queue event_queue; | 332 | static struct android_event_queue event_queue; |
| 303 | 333 | ||
| 304 | /* Semaphores used to signal select completion and start. */ | 334 | /* Main select loop of select threads. */ |
| 305 | static sem_t android_pselect_sem, android_pselect_start_sem; | 335 | static void *android_run_select_thread (void *); |
| 306 | 336 | ||
| 307 | #if __ANDROID_API__ < 16 | 337 | /* Initialize a thread-local component of the Android event queue |
| 338 | THREAD. Create and initialize a thread whose purpose is to execute | ||
| 339 | `select' in an interruptible manner, and initialize variables or file | ||
| 340 | descriptors with which to communicate with it. */ | ||
| 308 | 341 | ||
| 309 | /* Select self-pipe. */ | 342 | static void |
| 310 | static int select_pipe[2]; | 343 | android_init_thread_events (struct android_thread_event_queue *thread) |
| 344 | { | ||
| 345 | thread->canceled = false; | ||
| 346 | thread->select_readfds = NULL; | ||
| 347 | thread->select_writefds = NULL; | ||
| 348 | thread->select_exceptfds = NULL; | ||
| 349 | thread->select_timeout = NULL; | ||
| 350 | thread->select_nfds = 0; | ||
| 311 | 351 | ||
| 312 | #else | 352 | if (pthread_mutex_init (&thread->select_mutex, NULL)) |
| 353 | { | ||
| 354 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 355 | "pthread_mutex_init: %s", | ||
| 356 | strerror (errno)); | ||
| 357 | emacs_abort (); | ||
| 358 | } | ||
| 313 | 359 | ||
| 314 | /* Whether or not pselect has been interrupted. */ | 360 | sem_init (&thread->select_sem, 0, 0); |
| 315 | static volatile sig_atomic_t android_pselect_interrupted; | 361 | sem_init (&thread->start_sem, 0, 0); |
| 316 | 362 | ||
| 317 | #endif | 363 | #if __ANDROID_API__ < 21 |
| 364 | /* Set up the file descriptor used to wake up pselect. */ | ||
| 365 | if (pipe2 (thread->select_pipe, O_CLOEXEC) < 0) | ||
| 366 | { | ||
| 367 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 368 | "pipe2: %s", strerror (errno)); | ||
| 369 | emacs_abort (); | ||
| 370 | } | ||
| 371 | |||
| 372 | /* Make sure the read end will fit in fd_set. */ | ||
| 373 | if (thread->select_pipe[0] >= FD_SETSIZE) | ||
| 374 | { | ||
| 375 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 376 | "read end of select pipe" | ||
| 377 | " exceeds FD_SETSIZE!"); | ||
| 378 | emacs_abort (); | ||
| 379 | } | ||
| 380 | #endif /* __ANDROID_API__ < 21 */ | ||
| 381 | |||
| 382 | /* Start the select thread. */ | ||
| 383 | if (pthread_create (&thread->select_thread, NULL, | ||
| 384 | android_run_select_thread, thread)) | ||
| 385 | { | ||
| 386 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 387 | "pthread_create: %s", | ||
| 388 | strerror (errno)); | ||
| 389 | emacs_abort (); | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | #ifdef THREADS_ENABLED | ||
| 394 | |||
| 395 | /* Destroy a thread-local component of the Android event queue provided | ||
| 396 | as DATA, and release DATA's storage itself. Must be invoked at a | ||
| 397 | time when the select thread is idle, i.e., awaiting | ||
| 398 | DATA->start_sem. */ | ||
| 399 | |||
| 400 | static void | ||
| 401 | android_finalize_thread_events (void *data) | ||
| 402 | { | ||
| 403 | int rc; | ||
| 404 | struct android_thread_event_queue *thread; | ||
| 405 | |||
| 406 | /* Cancel the thread and pause till it exits. */ | ||
| 407 | thread = data; | ||
| 408 | thread->canceled = 1; | ||
| 409 | sem_post (&thread->start_sem); | ||
| 410 | rc = pthread_join (thread->select_thread, NULL); | ||
| 411 | if (rc) | ||
| 412 | emacs_abort (); | ||
| 413 | |||
| 414 | /* Release the select thread, semaphores, etc. */ | ||
| 415 | pthread_mutex_destroy (&thread->select_mutex); | ||
| 416 | sem_close (&thread->select_sem); | ||
| 417 | sem_close (&thread->start_sem); | ||
| 418 | #if __ANDROID_API__ < 21 | ||
| 419 | close (thread->select_pipe[0]); | ||
| 420 | close (thread->select_pipe[1]); | ||
| 421 | #endif /* __ANDROID_API__ < 21 */ | ||
| 422 | xfree (thread); | ||
| 423 | } | ||
| 424 | |||
| 425 | /* TLS keys associating polling threads with Emacs threads. */ | ||
| 426 | static pthread_key_t poll_thread, poll_thread_internal; | ||
| 427 | |||
| 428 | #endif /* THREADS_ENABLED */ | ||
| 429 | |||
| 430 | /* Return the thread-specific component of the event queue appertaining | ||
| 431 | to this thread, or create it as well as a polling thread if | ||
| 432 | absent. */ | ||
| 318 | 433 | ||
| 319 | /* Set the task name of the current task to NAME, a string at most 16 | 434 | static struct android_thread_event_queue * |
| 435 | android_get_poll_thread (void) | ||
| 436 | { | ||
| 437 | #ifndef THREADS_ENABLED | ||
| 438 | return &event_queue.thread; | ||
| 439 | #else /* THREADS_ENABLED */ | ||
| 440 | struct android_thread_event_queue *queue; | ||
| 441 | |||
| 442 | queue = pthread_getspecific (poll_thread); | ||
| 443 | if (!queue) | ||
| 444 | { | ||
| 445 | queue = xmalloc (sizeof *queue); | ||
| 446 | android_init_thread_events (queue); | ||
| 447 | pthread_setspecific (poll_thread, queue); | ||
| 448 | } | ||
| 449 | return queue; | ||
| 450 | #endif /* !THREADS_ENABLED */ | ||
| 451 | } | ||
| 452 | |||
| 453 | /* Set the task name of the current task to NAME, a string at most 21 | ||
| 320 | characters in length. | 454 | characters in length. |
| 321 | 455 | ||
| 322 | This name is displayed as that of the task (LWP)'s pthread in | 456 | This name is displayed as that of the task (LWP)'s pthread in |
| @@ -357,67 +491,73 @@ android_set_task_name (const char *name) | |||
| 357 | } | 491 | } |
| 358 | 492 | ||
| 359 | static void * | 493 | static void * |
| 360 | android_run_select_thread (void *data) | 494 | android_run_select_thread (void *thread_data) |
| 361 | { | 495 | { |
| 362 | /* Apparently this is required too. */ | 496 | /* Apparently this is required too. */ |
| 363 | JNI_STACK_ALIGNMENT_PROLOGUE; | 497 | JNI_STACK_ALIGNMENT_PROLOGUE; |
| 364 | 498 | ||
| 365 | int rc; | 499 | int rc; |
| 366 | #if __ANDROID_API__ < 16 | 500 | struct android_thread_event_queue *data; |
| 501 | #if __ANDROID_API__ < 21 | ||
| 367 | int nfds; | 502 | int nfds; |
| 368 | fd_set readfds; | 503 | fd_set readfds; |
| 369 | char byte; | 504 | char byte; |
| 370 | #else | 505 | #else /* __ANDROID_API__ >= 21 */ |
| 371 | sigset_t signals, waitset; | 506 | sigset_t signals, waitset; |
| 372 | int sig; | 507 | int sig; |
| 373 | #endif | 508 | #endif /* __ANDROID_API__ >= 21 */ |
| 374 | 509 | ||
| 375 | /* Set the name of this thread's LWP for debugging purposes. */ | 510 | /* Set the name of this thread's LWP for debugging purposes. */ |
| 376 | android_set_task_name ("`android_select'"); | 511 | android_set_task_name ("Emacs polling thread"); |
| 512 | data = thread_data; | ||
| 377 | 513 | ||
| 378 | #if __ANDROID_API__ < 16 | 514 | #if __ANDROID_API__ < 21 |
| 379 | /* A completely different implementation is used when building for | 515 | /* A completely different implementation is used when building for |
| 380 | Android versions earlier than 16, because pselect with a signal | 516 | Android versions earlier than 21, because pselect with a signal |
| 381 | mask does not work there. Instead of blocking SIGUSR1 and | 517 | mask does not work properly: the signal mask is truncated on APIs |
| 382 | unblocking it inside pselect, a file descriptor is used instead. | 518 | <= 16, and elsewhere, the signal mask is applied in userspace |
| 383 | Something is written to the file descriptor every time select is | 519 | before issuing a select system call, between which SELECT_SIGNAL |
| 384 | supposed to return. */ | 520 | may arrive. Instead of blocking SELECT_SIGNAL and unblocking it |
| 521 | inside pselect, a file descriptor is selected. Data is written to | ||
| 522 | the file descriptor whenever select is supposed to return. */ | ||
| 385 | 523 | ||
| 386 | while (true) | 524 | while (true) |
| 387 | { | 525 | { |
| 388 | /* Wait for the thread to be released. */ | 526 | /* Wait for the thread to be released. */ |
| 389 | while (sem_wait (&android_pselect_start_sem) < 0) | 527 | while (sem_wait (&data->start_sem) < 0) |
| 390 | ;; | 528 | ;; |
| 529 | if (data->canceled) | ||
| 530 | return NULL; | ||
| 391 | 531 | ||
| 392 | /* Get the select lock and call pselect. API 8 does not have | 532 | /* Get the select lock and call pselect. API 8 does not have |
| 393 | working pselect in any sense. Instead, pselect wakes up on | 533 | working pselect in any sense. Instead, pselect wakes up on |
| 394 | select_pipe[0]. */ | 534 | select_pipe[0]. */ |
| 395 | 535 | ||
| 396 | pthread_mutex_lock (&event_queue.select_mutex); | 536 | pthread_mutex_lock (&data->select_mutex); |
| 397 | nfds = android_pselect_nfds; | 537 | nfds = data->select_nfds; |
| 398 | 538 | ||
| 399 | if (android_pselect_readfds) | 539 | if (data->select_readfds) |
| 400 | readfds = *android_pselect_readfds; | 540 | readfds = *data->select_readfds; |
| 401 | else | 541 | else |
| 402 | FD_ZERO (&readfds); | 542 | FD_ZERO (&readfds); |
| 403 | 543 | ||
| 404 | if (nfds < select_pipe[0] + 1) | 544 | if (nfds < data->select_pipe[0] + 1) |
| 405 | nfds = select_pipe[0] + 1; | 545 | nfds = data->select_pipe[0] + 1; |
| 406 | FD_SET (select_pipe[0], &readfds); | 546 | FD_SET (data->select_pipe[0], &readfds); |
| 407 | 547 | ||
| 408 | rc = pselect (nfds, &readfds, | 548 | rc = pselect (nfds, &readfds, |
| 409 | android_pselect_writefds, | 549 | data->select_writefds, |
| 410 | android_pselect_exceptfds, | 550 | data->select_exceptfds, |
| 411 | android_pselect_timeout, | 551 | data->select_timeout, |
| 412 | NULL); | 552 | NULL); |
| 413 | 553 | ||
| 414 | /* Subtract 1 from rc if readfds contains the select pipe, and | 554 | /* Subtract 1 from rc if readfds contains the select pipe, and |
| 415 | also remove it from that set. */ | 555 | also remove it from that set. */ |
| 416 | 556 | ||
| 417 | if (rc != -1 && FD_ISSET (select_pipe[0], &readfds)) | 557 | if (rc != -1 && FD_ISSET (data->select_pipe[0], &readfds)) |
| 418 | { | 558 | { |
| 419 | rc -= 1; | 559 | rc -= 1; |
| 420 | FD_CLR (select_pipe[0], &readfds); | 560 | FD_CLR (data->select_pipe[0], &readfds); |
| 421 | 561 | ||
| 422 | /* If no file descriptors aside from the select pipe are | 562 | /* If no file descriptors aside from the select pipe are |
| 423 | ready, then pretend that an error has occurred. */ | 563 | ready, then pretend that an error has occurred. */ |
| @@ -427,11 +567,11 @@ android_run_select_thread (void *data) | |||
| 427 | 567 | ||
| 428 | /* Save the read file descriptor set back again. */ | 568 | /* Save the read file descriptor set back again. */ |
| 429 | 569 | ||
| 430 | if (android_pselect_readfds) | 570 | if (data->select_readfds) |
| 431 | *android_pselect_readfds = readfds; | 571 | *data->select_readfds = readfds; |
| 432 | 572 | ||
| 433 | android_pselect_rc = rc; | 573 | data->select_rc = rc; |
| 434 | pthread_mutex_unlock (&event_queue.select_mutex); | 574 | pthread_mutex_unlock (&data->select_mutex); |
| 435 | 575 | ||
| 436 | /* Signal the main thread that there is now data to read. Hold | 576 | /* Signal the main thread that there is now data to read. Hold |
| 437 | the event queue lock during this process to make sure this | 577 | the event queue lock during this process to make sure this |
| @@ -443,44 +583,46 @@ android_run_select_thread (void *data) | |||
| 443 | pthread_mutex_unlock (&event_queue.mutex); | 583 | pthread_mutex_unlock (&event_queue.mutex); |
| 444 | 584 | ||
| 445 | /* Read a single byte from the select pipe. */ | 585 | /* Read a single byte from the select pipe. */ |
| 446 | read (select_pipe[0], &byte, 1); | 586 | read (data->select_pipe[0], &byte, 1); |
| 447 | 587 | ||
| 448 | /* Signal the Emacs thread that pselect is done. If read_var | 588 | /* Signal the Emacs thread that pselect is done. If read_var |
| 449 | was signaled by android_write_event, event_queue.mutex could | 589 | was signaled by android_write_event, event_queue.mutex could |
| 450 | still be locked, so this must come before. */ | 590 | still be locked, so this must come before. */ |
| 451 | sem_post (&android_pselect_sem); | 591 | sem_post (&data->select_sem); |
| 452 | } | 592 | } |
| 453 | #else | 593 | #else /* __ANDROID_API__ >= 21 */ |
| 594 | sigfillset (&signals); | ||
| 454 | if (pthread_sigmask (SIG_BLOCK, &signals, NULL)) | 595 | if (pthread_sigmask (SIG_BLOCK, &signals, NULL)) |
| 455 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 596 | __android_log_print (ANDROID_LOG_FATAL, __func__, |
| 456 | "pthread_sigmask: %s", | 597 | "pthread_sigmask: %s", |
| 457 | strerror (errno)); | 598 | strerror (errno)); |
| 458 | 599 | ||
| 459 | sigfillset (&signals); | 600 | sigdelset (&signals, SELECT_SIGNAL); |
| 460 | sigdelset (&signals, SIGUSR1); | ||
| 461 | sigemptyset (&waitset); | 601 | sigemptyset (&waitset); |
| 462 | sigaddset (&waitset, SIGUSR1); | 602 | sigaddset (&waitset, SELECT_SIGNAL); |
| 603 | #ifdef THREADS_ENABLED | ||
| 604 | pthread_setspecific (poll_thread_internal, thread_data); | ||
| 605 | #endif /* THREADS_ENABLED */ | ||
| 463 | 606 | ||
| 464 | while (true) | 607 | while (true) |
| 465 | { | 608 | { |
| 466 | /* Wait for the thread to be released. */ | 609 | /* Wait for the thread to be released. */ |
| 467 | while (sem_wait (&android_pselect_start_sem) < 0) | 610 | while (sem_wait (&data->start_sem) < 0) |
| 468 | ;; | 611 | ;; |
| 469 | 612 | if (data->canceled) | |
| 470 | /* Clear the ``pselect interrupted'' flag. This is safe because | 613 | return NULL; |
| 471 | right now, SIGUSR1 is blocked. */ | ||
| 472 | android_pselect_interrupted = 0; | ||
| 473 | 614 | ||
| 474 | /* Get the select lock and call pselect. */ | 615 | /* Get the select lock and call pselect. */ |
| 475 | pthread_mutex_lock (&event_queue.select_mutex); | 616 | data->cancel_signal_received = 0; |
| 476 | rc = pselect (android_pselect_nfds, | 617 | pthread_mutex_lock (&data->select_mutex); |
| 477 | android_pselect_readfds, | 618 | rc = pselect (data->select_nfds, |
| 478 | android_pselect_writefds, | 619 | data->select_readfds, |
| 479 | android_pselect_exceptfds, | 620 | data->select_writefds, |
| 480 | android_pselect_timeout, | 621 | data->select_exceptfds, |
| 622 | data->select_timeout, | ||
| 481 | &signals); | 623 | &signals); |
| 482 | android_pselect_rc = rc; | 624 | data->select_rc = rc; |
| 483 | pthread_mutex_unlock (&event_queue.select_mutex); | 625 | pthread_mutex_unlock (&data->select_mutex); |
| 484 | 626 | ||
| 485 | /* Signal the main thread that there is now data to read. Hold | 627 | /* Signal the main thread that there is now data to read. Hold |
| 486 | the event queue lock during this process to make sure this | 628 | the event queue lock during this process to make sure this |
| @@ -491,39 +633,51 @@ android_run_select_thread (void *data) | |||
| 491 | pthread_cond_broadcast (&event_queue.read_var); | 633 | pthread_cond_broadcast (&event_queue.read_var); |
| 492 | pthread_mutex_unlock (&event_queue.mutex); | 634 | pthread_mutex_unlock (&event_queue.mutex); |
| 493 | 635 | ||
| 494 | /* Check `android_pselect_interrupted' instead of rc and errno. | 636 | /* Test a separate flag `data->cancel_signal_received' rather than |
| 637 | rc and errno. | ||
| 495 | 638 | ||
| 496 | This is because `pselect' does not return an rc of -1 upon | 639 | This is because `pselect' does not return an rc of -1 upon |
| 497 | being interrupted in some versions of Android, but does set | 640 | being interrupted in some versions of Android, but does set |
| 498 | signal masks correctly. */ | 641 | signal masks correctly. */ |
| 499 | 642 | if (!data->cancel_signal_received) | |
| 500 | if (!android_pselect_interrupted) | 643 | /* Now, wait for SELECT_SIGNAL, unless pselect was interrupted |
| 501 | /* Now, wait for SIGUSR1, unless pselect was interrupted and | 644 | and the signal has already been delivered. The Emacs thread |
| 502 | the signal was already delivered. The Emacs thread will | 645 | will always send this signal after read_var is triggered or |
| 503 | always send this signal after read_var is triggered or the | 646 | the UI thread has sent an event. */ |
| 504 | UI thread has sent an event. */ | ||
| 505 | sigwait (&waitset, &sig); | 647 | sigwait (&waitset, &sig); |
| 506 | 648 | ||
| 507 | /* Signal the Emacs thread that pselect is done. If read_var | 649 | /* Signal the Emacs thread that pselect is done. If read_var |
| 508 | was signaled by android_write_event, event_queue.mutex could | 650 | was signaled by android_write_event, event_queue.mutex could |
| 509 | still be locked, so this must come before. */ | 651 | still be locked, so this must come before. */ |
| 510 | sem_post (&android_pselect_sem); | 652 | sem_post (&data->select_sem); |
| 511 | } | 653 | } |
| 512 | #endif | 654 | #endif /* __ANDROID_API__ >= 21 */ |
| 513 | 655 | ||
| 514 | return NULL; | 656 | return NULL; |
| 515 | } | 657 | } |
| 516 | 658 | ||
| 517 | #if __ANDROID_API__ >= 16 | 659 | #if __ANDROID_API__ >= 21 |
| 518 | 660 | ||
| 519 | static void | 661 | static void |
| 520 | android_handle_sigusr1 (int sig, siginfo_t *siginfo, void *arg) | 662 | android_handle_poll_signal (int sig, siginfo_t *siginfo, void *arg) |
| 521 | { | 663 | { |
| 522 | /* Notice that pselect has been interrupted. */ | 664 | struct android_thread_event_queue *queue; |
| 523 | android_pselect_interrupted = 1; | 665 | |
| 666 | /* Although pthread_getspecific is not AS-safe, its implementation has | ||
| 667 | been verified to be safe to invoke from a single handler called | ||
| 668 | within pselect in a controlled manner, and this is the only means | ||
| 669 | of retrieving thread-specific data from a signal handler, as the | ||
| 670 | POSIX real-time signal system calls are unavailable to Android | ||
| 671 | applications. */ | ||
| 672 | #ifdef THREADS_ENABLED | ||
| 673 | queue = pthread_getspecific (poll_thread_internal); | ||
| 674 | #else /* !THREADS_ENABLED */ | ||
| 675 | queue = &event_queue.thread; | ||
| 676 | #endif /* !THREADS_ENABLED */ | ||
| 677 | queue->cancel_signal_received = 1; | ||
| 524 | } | 678 | } |
| 525 | 679 | ||
| 526 | #endif | 680 | #endif /* __ANDROID_API__ >= 21 */ |
| 527 | 681 | ||
| 528 | /* Semaphore used to indicate completion of a query. | 682 | /* Semaphore used to indicate completion of a query. |
| 529 | This should ideally be defined further down. */ | 683 | This should ideally be defined further down. */ |
| @@ -543,66 +697,57 @@ static pthread_t main_thread_id; | |||
| 543 | static void | 697 | static void |
| 544 | android_init_events (void) | 698 | android_init_events (void) |
| 545 | { | 699 | { |
| 700 | #if __ANDROID_API__ >= 21 | ||
| 546 | struct sigaction sa; | 701 | struct sigaction sa; |
| 702 | #endif /* __ANDROID_API__ >= 21 */ | ||
| 547 | 703 | ||
| 548 | if (pthread_mutex_init (&event_queue.mutex, NULL)) | 704 | if (pthread_mutex_init (&event_queue.mutex, NULL)) |
| 549 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 705 | { |
| 550 | "pthread_mutex_init: %s", | 706 | __android_log_print (ANDROID_LOG_FATAL, __func__, |
| 551 | strerror (errno)); | 707 | "pthread_mutex_init: %s", |
| 552 | 708 | strerror (errno)); | |
| 553 | if (pthread_mutex_init (&event_queue.select_mutex, NULL)) | 709 | emacs_abort (); |
| 554 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 710 | } |
| 555 | "pthread_mutex_init: %s", | ||
| 556 | strerror (errno)); | ||
| 557 | 711 | ||
| 558 | if (pthread_cond_init (&event_queue.read_var, NULL)) | 712 | if (pthread_cond_init (&event_queue.read_var, NULL)) |
| 559 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 713 | { |
| 560 | "pthread_cond_init: %s", | 714 | __android_log_print (ANDROID_LOG_FATAL, __func__, |
| 561 | strerror (errno)); | 715 | "pthread_cond_init: %s", |
| 562 | 716 | strerror (errno)); | |
| 563 | sem_init (&android_pselect_sem, 0, 0); | 717 | emacs_abort (); |
| 564 | sem_init (&android_pselect_start_sem, 0, 0); | 718 | } |
| 565 | sem_init (&android_query_sem, 0, 0); | ||
| 566 | 719 | ||
| 567 | event_queue.events.next = &event_queue.events; | 720 | event_queue.events.next = &event_queue.events; |
| 568 | event_queue.events.last = &event_queue.events; | 721 | event_queue.events.last = &event_queue.events; |
| 569 | 722 | ||
| 570 | main_thread_id = pthread_self (); | 723 | main_thread_id = pthread_self (); |
| 571 | 724 | ||
| 572 | #if __ANDROID_API__ >= 16 | 725 | #if __ANDROID_API__ >= 21 |
| 573 | 726 | /* Before any event threads are initialized, guarantee that the | |
| 574 | /* Before starting the select thread, make sure the disposition for | 727 | disposition of SELECT_SIGNAL is correct. */ |
| 575 | SIGUSR1 is correct. */ | ||
| 576 | sigfillset (&sa.sa_mask); | 728 | sigfillset (&sa.sa_mask); |
| 577 | sa.sa_sigaction = android_handle_sigusr1; | 729 | sa.sa_sigaction = android_handle_poll_signal; |
| 578 | sa.sa_flags = SA_SIGINFO; | 730 | sa.sa_flags = SA_SIGINFO; |
| 579 | 731 | if (sigaction (SELECT_SIGNAL, &sa, NULL)) | |
| 580 | #else | 732 | { |
| 581 | 733 | __android_log_print (ANDROID_LOG_FATAL, __func__, | |
| 582 | /* Set up the file descriptor used to wake up pselect. */ | 734 | "sigaction: %s", |
| 583 | if (pipe2 (select_pipe, O_CLOEXEC) < 0) | 735 | strerror (errno)); |
| 584 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 736 | emacs_abort (); |
| 585 | "pipe2: %s", strerror (errno)); | 737 | } |
| 586 | 738 | #endif /* __ANDROID_API__ >= 21 */ | |
| 587 | /* Make sure the read end will fit in fd_set. */ | 739 | #ifndef THREADS_ENABLED |
| 588 | if (select_pipe[0] >= FD_SETSIZE) | 740 | android_init_thread_events (&event_queue.thread); |
| 589 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 741 | #else /* THREADS_ENABLED */ |
| 590 | "read end of select pipe" | 742 | if (pthread_key_create (&poll_thread, android_finalize_thread_events) |
| 591 | " lies outside FD_SETSIZE!"); | 743 | || pthread_key_create (&poll_thread_internal, NULL)) |
| 592 | 744 | { | |
| 593 | #endif | 745 | __android_log_print (ANDROID_LOG_FATAL, __func__, |
| 594 | 746 | "pthread_key_create: %s", | |
| 595 | if (sigaction (SIGUSR1, &sa, NULL)) | 747 | strerror (errno)); |
| 596 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 748 | emacs_abort (); |
| 597 | "sigaction: %s", | 749 | } |
| 598 | strerror (errno)); | 750 | #endif /* THREADS_ENABLED */ |
| 599 | |||
| 600 | /* Start the select thread. */ | ||
| 601 | if (pthread_create (&event_queue.select_thread, NULL, | ||
| 602 | android_run_select_thread, NULL)) | ||
| 603 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 604 | "pthread_create: %s", | ||
| 605 | strerror (errno)); | ||
| 606 | } | 751 | } |
| 607 | 752 | ||
| 608 | int | 753 | int |
| @@ -761,25 +906,17 @@ int | |||
| 761 | android_select (int nfds, fd_set *readfds, fd_set *writefds, | 906 | android_select (int nfds, fd_set *readfds, fd_set *writefds, |
| 762 | fd_set *exceptfds, struct timespec *timeout) | 907 | fd_set *exceptfds, struct timespec *timeout) |
| 763 | { | 908 | { |
| 764 | int nfds_return; | 909 | int nfds_return, nevents; |
| 765 | #if __ANDROID_API__ < 16 | 910 | #if __ANDROID_API__ < 21 |
| 766 | static char byte; | 911 | static char byte; |
| 767 | #endif | 912 | #endif |
| 913 | struct android_thread_event_queue *data; | ||
| 768 | 914 | ||
| 769 | #ifdef THREADS_ENABLED | 915 | /* When threads are enabled, the following is executed before the |
| 770 | if (!pthread_equal (pthread_self (), main_thread_id)) | 916 | global lock is released. */ |
| 771 | return pselect (nfds, readfds, writefds, exceptfds, timeout, | 917 | #ifndef THREADS_ENABLED |
| 772 | NULL); | 918 | android_before_select (); |
| 773 | #endif /* THREADS_ENABLED */ | 919 | #endif /* !THREADS_ENABLED */ |
| 774 | |||
| 775 | /* Since Emacs is reading keyboard input again, signify that queries | ||
| 776 | from input methods are no longer ``urgent''. */ | ||
| 777 | |||
| 778 | __atomic_clear (&android_urgent_query, __ATOMIC_RELEASE); | ||
| 779 | |||
| 780 | /* Check for and run anything the UI thread wants to run on the main | ||
| 781 | thread. */ | ||
| 782 | android_check_query (); | ||
| 783 | 920 | ||
| 784 | pthread_mutex_lock (&event_queue.mutex); | 921 | pthread_mutex_lock (&event_queue.mutex); |
| 785 | 922 | ||
| @@ -804,60 +941,60 @@ android_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 804 | 941 | ||
| 805 | nfds_return = 0; | 942 | nfds_return = 0; |
| 806 | 943 | ||
| 807 | pthread_mutex_lock (&event_queue.select_mutex); | 944 | data = android_get_poll_thread (); |
| 808 | android_pselect_nfds = nfds; | 945 | |
| 809 | android_pselect_readfds = readfds; | 946 | pthread_mutex_lock (&data->select_mutex); |
| 810 | android_pselect_writefds = writefds; | 947 | data->select_nfds = nfds; |
| 811 | android_pselect_exceptfds = exceptfds; | 948 | data->select_readfds = readfds; |
| 812 | android_pselect_timeout = timeout; | 949 | data->select_writefds = writefds; |
| 813 | pthread_mutex_unlock (&event_queue.select_mutex); | 950 | data->select_exceptfds = exceptfds; |
| 951 | data->select_timeout = timeout; | ||
| 952 | pthread_mutex_unlock (&data->select_mutex); | ||
| 814 | 953 | ||
| 815 | /* Release the select thread. */ | 954 | /* Release the select thread. */ |
| 816 | sem_post (&android_pselect_start_sem); | 955 | sem_post (&data->start_sem); |
| 817 | 956 | ||
| 818 | /* Start waiting for the event queue condition to be set. */ | 957 | /* Start waiting for the event queue condition to be set. */ |
| 819 | pthread_cond_wait (&event_queue.read_var, &event_queue.mutex); | 958 | pthread_cond_wait (&event_queue.read_var, &event_queue.mutex); |
| 820 | 959 | ||
| 821 | #if __ANDROID_API__ >= 16 | 960 | #if __ANDROID_API__ >= 21 |
| 822 | /* Interrupt the select thread now, in case it's still in | 961 | /* Interrupt the select thread now, in case it's still in |
| 823 | pselect. */ | 962 | pselect. */ |
| 824 | pthread_kill (event_queue.select_thread, SIGUSR1); | 963 | pthread_kill (data->select_thread, SELECT_SIGNAL); |
| 825 | #else | 964 | #else /* __ANDROID_API__ < 21 */ |
| 826 | /* Interrupt the select thread by writing to the select pipe. */ | 965 | /* Interrupt the select thread by writing to the select pipe. */ |
| 827 | if (write (select_pipe[1], &byte, 1) != 1) | 966 | if (write (data->select_pipe[1], &byte, 1) != 1) |
| 828 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 967 | __android_log_print (ANDROID_LOG_FATAL, __func__, |
| 829 | "write: %s", strerror (errno)); | 968 | "write: %s", strerror (errno)); |
| 830 | #endif | 969 | #endif /* __ANDROID_API__ < 21 */ |
| 831 | 970 | ||
| 832 | /* Unlock the event queue mutex. */ | 971 | /* Are there any events in the event queue? */ |
| 972 | nevents = event_queue.num_events; | ||
| 833 | pthread_mutex_unlock (&event_queue.mutex); | 973 | pthread_mutex_unlock (&event_queue.mutex); |
| 834 | 974 | ||
| 835 | /* Wait for pselect to return in any case. This must be done with | 975 | /* Wait for pselect to return in any case. This must be done with the |
| 836 | the event queue mutex unlocked. Otherwise, the pselect thread | 976 | event queue mutex unlocked. Otherwise, the pselect thread can hang |
| 837 | can hang if it tries to lock the event queue mutex to signal | 977 | if it tries to lock the event queue mutex to signal read_var after |
| 838 | read_var after the UI thread has already done so. */ | 978 | the UI thread has already done so. */ |
| 839 | while (sem_wait (&android_pselect_sem) < 0) | 979 | while (sem_wait (&data->select_sem) < 0) |
| 840 | ;; | 980 | ;; |
| 841 | 981 | ||
| 842 | /* If there are now events in the queue, return 1. */ | 982 | /* If there are now events in the queue, return 1. */ |
| 843 | 983 | if (nevents) | |
| 844 | pthread_mutex_lock (&event_queue.mutex); | ||
| 845 | if (event_queue.num_events) | ||
| 846 | nfds_return = 1; | 984 | nfds_return = 1; |
| 847 | pthread_mutex_unlock (&event_queue.mutex); | ||
| 848 | 985 | ||
| 849 | /* Add the return value of pselect if it has also found ready file | 986 | /* Add the return value of pselect if it has also discovered ready |
| 850 | descriptors. */ | 987 | file descriptors. */ |
| 851 | 988 | ||
| 852 | if (android_pselect_rc >= 0) | 989 | if (data->select_rc >= 0) |
| 853 | nfds_return += android_pselect_rc; | 990 | nfds_return += data->select_rc; |
| 854 | else if (!nfds_return) | 991 | else if (!nfds_return) |
| 855 | /* If pselect was interrupted and nfds_return is 0 (meaning that | 992 | /* If pselect was interrupted and nfds_return is 0 (meaning that no |
| 856 | no events have been read), indicate that an error has taken | 993 | events have been read), indicate that an error has taken |
| 857 | place. */ | 994 | place. */ |
| 858 | nfds_return = android_pselect_rc; | 995 | nfds_return = data->select_rc; |
| 859 | 996 | ||
| 860 | if ((android_pselect_rc < 0) && nfds_return >= 0) | 997 | if ((data->select_rc < 0) && nfds_return >= 0) |
| 861 | { | 998 | { |
| 862 | /* Clear the file descriptor sets if events will be delivered | 999 | /* Clear the file descriptor sets if events will be delivered |
| 863 | but no file descriptors have become ready to prevent the | 1000 | but no file descriptors have become ready to prevent the |
| @@ -6721,6 +6858,23 @@ static void *android_query_context; | |||
| 6721 | itself; however, the input signal handler executes a memory fence | 6858 | itself; however, the input signal handler executes a memory fence |
| 6722 | to ensure that all query related writes become visible. */ | 6859 | to ensure that all query related writes become visible. */ |
| 6723 | 6860 | ||
| 6861 | /* Clear the ``urgent query'' flag and run any function that the UI | ||
| 6862 | thread has asked to run. Must be invoked before `android_select' | ||
| 6863 | from the thread holding the global lock. */ | ||
| 6864 | |||
| 6865 | void | ||
| 6866 | android_before_select (void) | ||
| 6867 | { | ||
| 6868 | /* Since Emacs is reading keyboard input again, signify that queries | ||
| 6869 | from input methods are no longer ``urgent''. */ | ||
| 6870 | |||
| 6871 | __atomic_clear (&android_urgent_query, __ATOMIC_RELEASE); | ||
| 6872 | |||
| 6873 | /* Check for and run anything the UI thread wants to run on the main | ||
| 6874 | thread. */ | ||
| 6875 | android_check_query (); | ||
| 6876 | } | ||
| 6877 | |||
| 6724 | /* Run any function that the UI thread has asked to run, and then | 6878 | /* Run any function that the UI thread has asked to run, and then |
| 6725 | signal its completion. */ | 6879 | signal its completion. */ |
| 6726 | 6880 | ||
| @@ -6781,7 +6935,7 @@ android_check_query_urgent (void) | |||
| 6781 | if (!proc) | 6935 | if (!proc) |
| 6782 | return; | 6936 | return; |
| 6783 | 6937 | ||
| 6784 | proc (closure); | 6938 | (*proc) (closure); |
| 6785 | 6939 | ||
| 6786 | /* Finish the query. Don't clear `android_urgent_query'; instead, | 6940 | /* Finish the query. Don't clear `android_urgent_query'; instead, |
| 6787 | do that the next time Emacs enters the keyboard loop. */ | 6941 | do that the next time Emacs enters the keyboard loop. */ |
| @@ -6931,8 +7085,8 @@ android_run_in_emacs_thread (void (*proc) (void *), void *closure) | |||
| 6931 | /* Send a dummy event. `android_check_query' will be called inside | 7085 | /* Send a dummy event. `android_check_query' will be called inside |
| 6932 | wait_reading_process_output after the event arrives. | 7086 | wait_reading_process_output after the event arrives. |
| 6933 | 7087 | ||
| 6934 | Otherwise, android_select will call android_check_thread the next | 7088 | Otherwise, android_select will call `android_check_query' when next |
| 6935 | time it is entered. */ | 7089 | it is entered. */ |
| 6936 | android_write_event (&event); | 7090 | android_write_event (&event); |
| 6937 | 7091 | ||
| 6938 | /* Start waiting for the function to be executed. First, wait two | 7092 | /* Start waiting for the function to be executed. First, wait two |