diff options
| author | Eli Zaretskii | 2016-12-10 18:54:43 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-12-10 18:54:43 +0200 |
| commit | 2412a1fc05fe9f89b171d0781c2d530923f48adc (patch) | |
| tree | d42a5d2608e65a10b1cc23c6b4609d54bef25d49 /src/process.c | |
| parent | fc0fd24c105bde4c001ebebe4b8b7e1f96cd2871 (diff) | |
| parent | 828b4560cd4a0d8cb9b7a7a3e20ff0c53ba86cfa (diff) | |
| download | emacs-2412a1fc05fe9f89b171d0781c2d530923f48adc.tar.gz emacs-2412a1fc05fe9f89b171d0781c2d530923f48adc.zip | |
Support concurrency in Emacs Lisp
Merge branch 'test-concurrency'
* src/thread.c:
* src/thread.h:
* src/systhread.c:
* src/systhread.h: New files.
* src/xgselect.c (xg_select): Avoid using SAFE_NALLOCA and use
xnmalloc unconditionally.
* src/window.c (struct save_window_data): Rename current_buffer to
f_current_buffer.
* src/w32proc.c (sys_select): Change the function signature to
closer fit 'pselect' on Posix hosts.
* src/search.c:
* src/regex.h: Convert some globals to macros that reference
thread-specific values.
* src/process.c (pset_thread, add_non_keyboard_read_fd)
(add_process_read_fd, add_non_blocking_write_fd)
(recompute_input_desc, compute_input_wait_mask)
(compute_non_process_wait_mask, compute_non_keyboard_wait_mask)
(compute_write_mask, clear_waiting_thread_info)
(update_processes_for_thread_death, Fset_process_thread)
(Fprocess_thread): New functions.
(enum fd_bits): New enumeration.
(fd_callback_data): Add 'thread' and 'waiting_thread', rename
'condition' to 'flags'.
(set_process_filter_masks, create_process, create_pty)
(Fmake_serial_process, finish_after_tls_connection)
(connect_network_socket, deactivate_process)
(server_accept_connection, wait_reading_process_output)
(Fcontinue_process, Fstop_process, keyboard_bit_set)
(add_timer_wait_descriptor, add_keyboard_wait_descriptor)
(delete_keyboard_wait_descriptor): Use the new functions instead
of manipulating fd flags and masks directly.
(syms_of_process): Defsubr the new primitives.
* src/print.c (print_object): Print threads, mutexes, and
conditional variables.
* src/lisp.h (enum pvec_type): New values PVEC_THREAD, PVEC_MUTEX,
and PVEC_CONDVAR.
(XTHREAD, XMUTEX, XCONDVAR, THREADP, MUTEXP, CONDVARP)
(CHECK_THREAD, CHECK_MUTEX, CHECK_CONDVAR): New inline functions.
(XSETTHREAD, XSETMUTEX, XSETCONDVAR): New macros.
(struct handler): Add back byte_stack. Rename lisp_eval_depth to
f_lisp_eval_depth.
* src/eval.c (specpdl_kind, specpdl_arg, do_specbind)
(rebind_for_thread_switch, do_one_unbind)
(unbind_for_thread_switch): New functions.
(init_eval): 'handlerlist' is not malloc'ed.
(specbind): Call do_specbind.
(unbind_to): Call do_one_unbind.
(mark_specpdl): Accept 2 arguments.
(mark_specpdl): Mark the saved value in a let-binding.
* src/emacs.c (main): Call init_threads_once, init_threads, and
syms_of_threads.
* src/data.c (Ftype_of): Support thread, mutex, and condvar
objects.
(Fthreadp, Fmutexp, Fcondition_variable_p): New functions.
(syms_of_data): DEFSYM and defsubr new symbols and primitives.
* src/bytecode.c (struct byte_stack, FETCH, CHECK_RANGE)
(BYTE_CODE_QUIT): Add back.
(exec_byte_code): Add back byte stack manipulation.
* src/alloc.c (cleanup_vector): Handle threads, mutexes, and
conditional variables.
(mark_stack): Now extern; accept additional argument 'bottom'.
(flush_stack_call_func): New function.
(garbage_collect_1): Call mark_threads and unmark_threads. Don't
mark handlers.
* src/.gdbinit (xbytecode): Add back.
* test/src/thread-tests.el: New tests.
* test/src/data-tests.el (binding-test-manual)
(binding-test-setq-default, binding-test-makunbound)
(binding-test-defvar-bool, binding-test-defvar-int)
(binding-test-set-constant-t, binding-test-set-constant-nil)
(binding-test-set-constant-keyword)
(binding-test-set-constant-nil): New tests.
* doc/lispref/processes.texi (Processes and Threads): New
subsection.
* doc/lispref/threads.texi: New file
* doc/lispref/elisp.texi (Top): Include it.
* doc/lispref/objects.texi (Thread Type, Mutex Type)
(Condition Variable Type): New subsections.
(Type Predicates): Add thread-related predicates.
* doc/lispref/objects.texi (Editing Types):
* doc/lispref/elisp.texi (Top): Update higher-level menus.
* etc/NEWS: Mention concurrency features.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 547 |
1 files changed, 343 insertions, 204 deletions
diff --git a/src/process.c b/src/process.c index 8ab73bd9ae6..31c9d74a3f2 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -138,7 +138,7 @@ static struct rlimit nofile_limit; | |||
| 138 | 138 | ||
| 139 | #ifdef WINDOWSNT | 139 | #ifdef WINDOWSNT |
| 140 | extern int sys_select (int, fd_set *, fd_set *, fd_set *, | 140 | extern int sys_select (int, fd_set *, fd_set *, fd_set *, |
| 141 | struct timespec *, void *); | 141 | const struct timespec *, const sigset_t *); |
| 142 | #endif | 142 | #endif |
| 143 | 143 | ||
| 144 | /* Work around GCC 4.3.0 bug with strict overflow checking; see | 144 | /* Work around GCC 4.3.0 bug with strict overflow checking; see |
| @@ -260,36 +260,11 @@ static int read_process_output (Lisp_Object, int); | |||
| 260 | static void create_pty (Lisp_Object); | 260 | static void create_pty (Lisp_Object); |
| 261 | static void exec_sentinel (Lisp_Object, Lisp_Object); | 261 | static void exec_sentinel (Lisp_Object, Lisp_Object); |
| 262 | 262 | ||
| 263 | /* Mask of bits indicating the descriptors that we wait for input on. */ | ||
| 264 | |||
| 265 | static fd_set input_wait_mask; | ||
| 266 | |||
| 267 | /* Mask that excludes keyboard input descriptor(s). */ | ||
| 268 | |||
| 269 | static fd_set non_keyboard_wait_mask; | ||
| 270 | |||
| 271 | /* Mask that excludes process input descriptor(s). */ | ||
| 272 | |||
| 273 | static fd_set non_process_wait_mask; | ||
| 274 | |||
| 275 | /* Mask for selecting for write. */ | ||
| 276 | |||
| 277 | static fd_set write_mask; | ||
| 278 | |||
| 279 | /* Mask of bits indicating the descriptors that we wait for connect to | ||
| 280 | complete on. Once they complete, they are removed from this mask | ||
| 281 | and added to the input_wait_mask and non_keyboard_wait_mask. */ | ||
| 282 | |||
| 283 | static fd_set connect_wait_mask; | ||
| 284 | |||
| 285 | /* Number of bits set in connect_wait_mask. */ | 263 | /* Number of bits set in connect_wait_mask. */ |
| 286 | static int num_pending_connects; | 264 | static int num_pending_connects; |
| 287 | 265 | ||
| 288 | /* The largest descriptor currently in use for a process object; -1 if none. */ | 266 | /* The largest descriptor currently in use; -1 if none. */ |
| 289 | static int max_process_desc; | 267 | static int max_desc; |
| 290 | |||
| 291 | /* The largest descriptor currently in use for input; -1 if none. */ | ||
| 292 | static int max_input_desc; | ||
| 293 | 268 | ||
| 294 | /* Set the external socket descriptor for Emacs to use when | 269 | /* Set the external socket descriptor for Emacs to use when |
| 295 | `make-network-process' is called with a non-nil | 270 | `make-network-process' is called with a non-nil |
| @@ -384,6 +359,11 @@ pset_mark (struct Lisp_Process *p, Lisp_Object val) | |||
| 384 | p->mark = val; | 359 | p->mark = val; |
| 385 | } | 360 | } |
| 386 | static void | 361 | static void |
| 362 | pset_thread (struct Lisp_Process *p, Lisp_Object val) | ||
| 363 | { | ||
| 364 | p->thread = val; | ||
| 365 | } | ||
| 366 | static void | ||
| 387 | pset_name (struct Lisp_Process *p, Lisp_Object val) | 367 | pset_name (struct Lisp_Process *p, Lisp_Object val) |
| 388 | { | 368 | { |
| 389 | p->name = val; | 369 | p->name = val; |
| @@ -426,13 +406,34 @@ make_lisp_proc (struct Lisp_Process *p) | |||
| 426 | return make_lisp_ptr (p, Lisp_Vectorlike); | 406 | return make_lisp_ptr (p, Lisp_Vectorlike); |
| 427 | } | 407 | } |
| 428 | 408 | ||
| 409 | enum fd_bits | ||
| 410 | { | ||
| 411 | /* Read from file descriptor. */ | ||
| 412 | FOR_READ = 1, | ||
| 413 | /* Write to file descriptor. */ | ||
| 414 | FOR_WRITE = 2, | ||
| 415 | /* This descriptor refers to a keyboard. Only valid if FOR_READ is | ||
| 416 | set. */ | ||
| 417 | KEYBOARD_FD = 4, | ||
| 418 | /* This descriptor refers to a process. */ | ||
| 419 | PROCESS_FD = 8, | ||
| 420 | /* A non-blocking connect. Only valid if FOR_WRITE is set. */ | ||
| 421 | NON_BLOCKING_CONNECT_FD = 16 | ||
| 422 | }; | ||
| 423 | |||
| 429 | static struct fd_callback_data | 424 | static struct fd_callback_data |
| 430 | { | 425 | { |
| 431 | fd_callback func; | 426 | fd_callback func; |
| 432 | void *data; | 427 | void *data; |
| 433 | #define FOR_READ 1 | 428 | /* Flags from enum fd_bits. */ |
| 434 | #define FOR_WRITE 2 | 429 | int flags; |
| 435 | int condition; /* Mask of the defines above. */ | 430 | /* If this fd is locked to a certain thread, this points to it. |
| 431 | Otherwise, this is NULL. If an fd is locked to a thread, then | ||
| 432 | only that thread is permitted to wait on it. */ | ||
| 433 | struct thread_state *thread; | ||
| 434 | /* If this fd is currently being selected on by a thread, this | ||
| 435 | points to the thread. Otherwise it is NULL. */ | ||
| 436 | struct thread_state *waiting_thread; | ||
| 436 | } fd_callback_info[FD_SETSIZE]; | 437 | } fd_callback_info[FD_SETSIZE]; |
| 437 | 438 | ||
| 438 | 439 | ||
| @@ -446,7 +447,25 @@ add_read_fd (int fd, fd_callback func, void *data) | |||
| 446 | 447 | ||
| 447 | fd_callback_info[fd].func = func; | 448 | fd_callback_info[fd].func = func; |
| 448 | fd_callback_info[fd].data = data; | 449 | fd_callback_info[fd].data = data; |
| 449 | fd_callback_info[fd].condition |= FOR_READ; | 450 | } |
| 451 | |||
| 452 | static void | ||
| 453 | add_non_keyboard_read_fd (int fd) | ||
| 454 | { | ||
| 455 | eassert (fd >= 0 && fd < FD_SETSIZE); | ||
| 456 | eassert (fd_callback_info[fd].func == NULL); | ||
| 457 | |||
| 458 | fd_callback_info[fd].flags &= ~KEYBOARD_FD; | ||
| 459 | fd_callback_info[fd].flags |= FOR_READ; | ||
| 460 | if (fd > max_desc) | ||
| 461 | max_desc = fd; | ||
| 462 | } | ||
| 463 | |||
| 464 | static void | ||
| 465 | add_process_read_fd (int fd) | ||
| 466 | { | ||
| 467 | add_non_keyboard_read_fd (fd); | ||
| 468 | fd_callback_info[fd].flags |= PROCESS_FD; | ||
| 450 | } | 469 | } |
| 451 | 470 | ||
| 452 | /* Stop monitoring file descriptor FD for when read is possible. */ | 471 | /* Stop monitoring file descriptor FD for when read is possible. */ |
| @@ -456,8 +475,7 @@ delete_read_fd (int fd) | |||
| 456 | { | 475 | { |
| 457 | delete_keyboard_wait_descriptor (fd); | 476 | delete_keyboard_wait_descriptor (fd); |
| 458 | 477 | ||
| 459 | fd_callback_info[fd].condition &= ~FOR_READ; | 478 | if (fd_callback_info[fd].flags == 0) |
| 460 | if (fd_callback_info[fd].condition == 0) | ||
| 461 | { | 479 | { |
| 462 | fd_callback_info[fd].func = 0; | 480 | fd_callback_info[fd].func = 0; |
| 463 | fd_callback_info[fd].data = 0; | 481 | fd_callback_info[fd].data = 0; |
| @@ -470,28 +488,39 @@ delete_read_fd (int fd) | |||
| 470 | void | 488 | void |
| 471 | add_write_fd (int fd, fd_callback func, void *data) | 489 | add_write_fd (int fd, fd_callback func, void *data) |
| 472 | { | 490 | { |
| 473 | FD_SET (fd, &write_mask); | 491 | eassert (fd >= 0 && fd < FD_SETSIZE); |
| 474 | if (fd > max_input_desc) | ||
| 475 | max_input_desc = fd; | ||
| 476 | 492 | ||
| 477 | fd_callback_info[fd].func = func; | 493 | fd_callback_info[fd].func = func; |
| 478 | fd_callback_info[fd].data = data; | 494 | fd_callback_info[fd].data = data; |
| 479 | fd_callback_info[fd].condition |= FOR_WRITE; | 495 | fd_callback_info[fd].flags |= FOR_WRITE; |
| 496 | if (fd > max_desc) | ||
| 497 | max_desc = fd; | ||
| 480 | } | 498 | } |
| 481 | 499 | ||
| 482 | /* FD is no longer an input descriptor; update max_input_desc accordingly. */ | 500 | static void |
| 501 | add_non_blocking_write_fd (int fd) | ||
| 502 | { | ||
| 503 | eassert (fd >= 0 && fd < FD_SETSIZE); | ||
| 504 | eassert (fd_callback_info[fd].func == NULL); | ||
| 505 | |||
| 506 | fd_callback_info[fd].flags |= FOR_WRITE | NON_BLOCKING_CONNECT_FD; | ||
| 507 | if (fd > max_desc) | ||
| 508 | max_desc = fd; | ||
| 509 | ++num_pending_connects; | ||
| 510 | } | ||
| 483 | 511 | ||
| 484 | static void | 512 | static void |
| 485 | delete_input_desc (int fd) | 513 | recompute_max_desc (void) |
| 486 | { | 514 | { |
| 487 | if (fd == max_input_desc) | 515 | int fd; |
| 488 | { | ||
| 489 | do | ||
| 490 | fd--; | ||
| 491 | while (0 <= fd && ! (FD_ISSET (fd, &input_wait_mask) | ||
| 492 | || FD_ISSET (fd, &write_mask))); | ||
| 493 | 516 | ||
| 494 | max_input_desc = fd; | 517 | for (fd = max_desc; fd >= 0; --fd) |
| 518 | { | ||
| 519 | if (fd_callback_info[fd].flags != 0) | ||
| 520 | { | ||
| 521 | max_desc = fd; | ||
| 522 | break; | ||
| 523 | } | ||
| 495 | } | 524 | } |
| 496 | } | 525 | } |
| 497 | 526 | ||
| @@ -500,13 +529,121 @@ delete_input_desc (int fd) | |||
| 500 | void | 529 | void |
| 501 | delete_write_fd (int fd) | 530 | delete_write_fd (int fd) |
| 502 | { | 531 | { |
| 503 | FD_CLR (fd, &write_mask); | 532 | if ((fd_callback_info[fd].flags & NON_BLOCKING_CONNECT_FD) != 0) |
| 504 | fd_callback_info[fd].condition &= ~FOR_WRITE; | 533 | { |
| 505 | if (fd_callback_info[fd].condition == 0) | 534 | if (--num_pending_connects < 0) |
| 535 | emacs_abort (); | ||
| 536 | } | ||
| 537 | fd_callback_info[fd].flags &= ~(FOR_WRITE | NON_BLOCKING_CONNECT_FD); | ||
| 538 | if (fd_callback_info[fd].flags == 0) | ||
| 506 | { | 539 | { |
| 507 | fd_callback_info[fd].func = 0; | 540 | fd_callback_info[fd].func = 0; |
| 508 | fd_callback_info[fd].data = 0; | 541 | fd_callback_info[fd].data = 0; |
| 509 | delete_input_desc (fd); | 542 | |
| 543 | if (fd == max_desc) | ||
| 544 | recompute_max_desc (); | ||
| 545 | } | ||
| 546 | } | ||
| 547 | |||
| 548 | static void | ||
| 549 | compute_input_wait_mask (fd_set *mask) | ||
| 550 | { | ||
| 551 | int fd; | ||
| 552 | |||
| 553 | FD_ZERO (mask); | ||
| 554 | for (fd = 0; fd <= max_desc; ++fd) | ||
| 555 | { | ||
| 556 | if (fd_callback_info[fd].thread != NULL | ||
| 557 | && fd_callback_info[fd].thread != current_thread) | ||
| 558 | continue; | ||
| 559 | if (fd_callback_info[fd].waiting_thread != NULL | ||
| 560 | && fd_callback_info[fd].waiting_thread != current_thread) | ||
| 561 | continue; | ||
| 562 | if ((fd_callback_info[fd].flags & FOR_READ) != 0) | ||
| 563 | { | ||
| 564 | FD_SET (fd, mask); | ||
| 565 | fd_callback_info[fd].waiting_thread = current_thread; | ||
| 566 | } | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 570 | static void | ||
| 571 | compute_non_process_wait_mask (fd_set *mask) | ||
| 572 | { | ||
| 573 | int fd; | ||
| 574 | |||
| 575 | FD_ZERO (mask); | ||
| 576 | for (fd = 0; fd <= max_desc; ++fd) | ||
| 577 | { | ||
| 578 | if (fd_callback_info[fd].thread != NULL | ||
| 579 | && fd_callback_info[fd].thread != current_thread) | ||
| 580 | continue; | ||
| 581 | if (fd_callback_info[fd].waiting_thread != NULL | ||
| 582 | && fd_callback_info[fd].waiting_thread != current_thread) | ||
| 583 | continue; | ||
| 584 | if ((fd_callback_info[fd].flags & FOR_READ) != 0 | ||
| 585 | && (fd_callback_info[fd].flags & PROCESS_FD) == 0) | ||
| 586 | { | ||
| 587 | FD_SET (fd, mask); | ||
| 588 | fd_callback_info[fd].waiting_thread = current_thread; | ||
| 589 | } | ||
| 590 | } | ||
| 591 | } | ||
| 592 | |||
| 593 | static void | ||
| 594 | compute_non_keyboard_wait_mask (fd_set *mask) | ||
| 595 | { | ||
| 596 | int fd; | ||
| 597 | |||
| 598 | FD_ZERO (mask); | ||
| 599 | for (fd = 0; fd <= max_desc; ++fd) | ||
| 600 | { | ||
| 601 | if (fd_callback_info[fd].thread != NULL | ||
| 602 | && fd_callback_info[fd].thread != current_thread) | ||
| 603 | continue; | ||
| 604 | if (fd_callback_info[fd].waiting_thread != NULL | ||
| 605 | && fd_callback_info[fd].waiting_thread != current_thread) | ||
| 606 | continue; | ||
| 607 | if ((fd_callback_info[fd].flags & FOR_READ) != 0 | ||
| 608 | && (fd_callback_info[fd].flags & KEYBOARD_FD) == 0) | ||
| 609 | { | ||
| 610 | FD_SET (fd, mask); | ||
| 611 | fd_callback_info[fd].waiting_thread = current_thread; | ||
| 612 | } | ||
| 613 | } | ||
| 614 | } | ||
| 615 | |||
| 616 | static void | ||
| 617 | compute_write_mask (fd_set *mask) | ||
| 618 | { | ||
| 619 | int fd; | ||
| 620 | |||
| 621 | FD_ZERO (mask); | ||
| 622 | for (fd = 0; fd <= max_desc; ++fd) | ||
| 623 | { | ||
| 624 | if (fd_callback_info[fd].thread != NULL | ||
| 625 | && fd_callback_info[fd].thread != current_thread) | ||
| 626 | continue; | ||
| 627 | if (fd_callback_info[fd].waiting_thread != NULL | ||
| 628 | && fd_callback_info[fd].waiting_thread != current_thread) | ||
| 629 | continue; | ||
| 630 | if ((fd_callback_info[fd].flags & FOR_WRITE) != 0) | ||
| 631 | { | ||
| 632 | FD_SET (fd, mask); | ||
| 633 | fd_callback_info[fd].waiting_thread = current_thread; | ||
| 634 | } | ||
| 635 | } | ||
| 636 | } | ||
| 637 | |||
| 638 | static void | ||
| 639 | clear_waiting_thread_info (void) | ||
| 640 | { | ||
| 641 | int fd; | ||
| 642 | |||
| 643 | for (fd = 0; fd <= max_desc; ++fd) | ||
| 644 | { | ||
| 645 | if (fd_callback_info[fd].waiting_thread == current_thread) | ||
| 646 | fd_callback_info[fd].waiting_thread = NULL; | ||
| 510 | } | 647 | } |
| 511 | } | 648 | } |
| 512 | 649 | ||
| @@ -716,6 +853,7 @@ make_process (Lisp_Object name) | |||
| 716 | Lisp data to nil, so do it only for slots which should not be nil. */ | 853 | Lisp data to nil, so do it only for slots which should not be nil. */ |
| 717 | pset_status (p, Qrun); | 854 | pset_status (p, Qrun); |
| 718 | pset_mark (p, Fmake_marker ()); | 855 | pset_mark (p, Fmake_marker ()); |
| 856 | pset_thread (p, Fcurrent_thread ()); | ||
| 719 | 857 | ||
| 720 | /* Initialize non-Lisp data. Note that allocate_process zeroes out all | 858 | /* Initialize non-Lisp data. Note that allocate_process zeroes out all |
| 721 | non-Lisp data, so do it only for slots which should not be zero. */ | 859 | non-Lisp data, so do it only for slots which should not be zero. */ |
| @@ -764,6 +902,27 @@ remove_process (register Lisp_Object proc) | |||
| 764 | deactivate_process (proc); | 902 | deactivate_process (proc); |
| 765 | } | 903 | } |
| 766 | 904 | ||
| 905 | void | ||
| 906 | update_processes_for_thread_death (Lisp_Object dying_thread) | ||
| 907 | { | ||
| 908 | Lisp_Object pair; | ||
| 909 | |||
| 910 | for (pair = Vprocess_alist; !NILP (pair); pair = XCDR (pair)) | ||
| 911 | { | ||
| 912 | Lisp_Object process = XCDR (XCAR (pair)); | ||
| 913 | if (EQ (XPROCESS (process)->thread, dying_thread)) | ||
| 914 | { | ||
| 915 | struct Lisp_Process *proc = XPROCESS (process); | ||
| 916 | |||
| 917 | pset_thread (proc, Qnil); | ||
| 918 | if (proc->infd >= 0) | ||
| 919 | fd_callback_info[proc->infd].thread = NULL; | ||
| 920 | if (proc->outfd >= 0) | ||
| 921 | fd_callback_info[proc->outfd].thread = NULL; | ||
| 922 | } | ||
| 923 | } | ||
| 924 | } | ||
| 925 | |||
| 767 | #ifdef HAVE_GETADDRINFO_A | 926 | #ifdef HAVE_GETADDRINFO_A |
| 768 | static void | 927 | static void |
| 769 | free_dns_request (Lisp_Object proc) | 928 | free_dns_request (Lisp_Object proc) |
| @@ -1066,17 +1225,11 @@ static void | |||
| 1066 | set_process_filter_masks (struct Lisp_Process *p) | 1225 | set_process_filter_masks (struct Lisp_Process *p) |
| 1067 | { | 1226 | { |
| 1068 | if (EQ (p->filter, Qt) && !EQ (p->status, Qlisten)) | 1227 | if (EQ (p->filter, Qt) && !EQ (p->status, Qlisten)) |
| 1069 | { | 1228 | delete_read_fd (p->infd); |
| 1070 | FD_CLR (p->infd, &input_wait_mask); | ||
| 1071 | FD_CLR (p->infd, &non_keyboard_wait_mask); | ||
| 1072 | } | ||
| 1073 | else if (EQ (p->filter, Qt) | 1229 | else if (EQ (p->filter, Qt) |
| 1074 | /* Network or serial process not stopped: */ | 1230 | /* Network or serial process not stopped: */ |
| 1075 | && !EQ (p->command, Qt)) | 1231 | && !EQ (p->command, Qt)) |
| 1076 | { | 1232 | add_process_read_fd (p->infd); |
| 1077 | FD_SET (p->infd, &input_wait_mask); | ||
| 1078 | FD_SET (p->infd, &non_keyboard_wait_mask); | ||
| 1079 | } | ||
| 1080 | } | 1233 | } |
| 1081 | 1234 | ||
| 1082 | DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter, | 1235 | DEFUN ("set-process-filter", Fset_process_filter, Sset_process_filter, |
| @@ -1163,6 +1316,44 @@ See `set-process-sentinel' for more info on sentinels. */) | |||
| 1163 | return XPROCESS (process)->sentinel; | 1316 | return XPROCESS (process)->sentinel; |
| 1164 | } | 1317 | } |
| 1165 | 1318 | ||
| 1319 | DEFUN ("set-process-thread", Fset_process_thread, Sset_process_thread, | ||
| 1320 | 2, 2, 0, | ||
| 1321 | doc: /* Set the locking thread of PROCESS to be THREAD. | ||
| 1322 | If THREAD is nil, the process is unlocked. */) | ||
| 1323 | (Lisp_Object process, Lisp_Object thread) | ||
| 1324 | { | ||
| 1325 | struct Lisp_Process *proc; | ||
| 1326 | struct thread_state *tstate; | ||
| 1327 | |||
| 1328 | CHECK_PROCESS (process); | ||
| 1329 | if (NILP (thread)) | ||
| 1330 | tstate = NULL; | ||
| 1331 | else | ||
| 1332 | { | ||
| 1333 | CHECK_THREAD (thread); | ||
| 1334 | tstate = XTHREAD (thread); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | proc = XPROCESS (process); | ||
| 1338 | pset_thread (proc, thread); | ||
| 1339 | if (proc->infd >= 0) | ||
| 1340 | fd_callback_info[proc->infd].thread = tstate; | ||
| 1341 | if (proc->outfd >= 0) | ||
| 1342 | fd_callback_info[proc->outfd].thread = tstate; | ||
| 1343 | |||
| 1344 | return thread; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | DEFUN ("process-thread", Fprocess_thread, Sprocess_thread, | ||
| 1348 | 1, 1, 0, | ||
| 1349 | doc: /* Ret the locking thread of PROCESS. | ||
| 1350 | If PROCESS is unlocked, this function returns nil. */) | ||
| 1351 | (Lisp_Object process) | ||
| 1352 | { | ||
| 1353 | CHECK_PROCESS (process); | ||
| 1354 | return XPROCESS (process)->thread; | ||
| 1355 | } | ||
| 1356 | |||
| 1166 | DEFUN ("set-process-window-size", Fset_process_window_size, | 1357 | DEFUN ("set-process-window-size", Fset_process_window_size, |
| 1167 | Sset_process_window_size, 3, 3, 0, | 1358 | Sset_process_window_size, 3, 3, 0, |
| 1168 | doc: /* Tell PROCESS that it has logical window size WIDTH by HEIGHT. | 1359 | doc: /* Tell PROCESS that it has logical window size WIDTH by HEIGHT. |
| @@ -1840,13 +2031,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) | |||
| 1840 | pset_status (p, Qrun); | 2031 | pset_status (p, Qrun); |
| 1841 | 2032 | ||
| 1842 | if (!EQ (p->command, Qt)) | 2033 | if (!EQ (p->command, Qt)) |
| 1843 | { | 2034 | add_process_read_fd (inchannel); |
| 1844 | FD_SET (inchannel, &input_wait_mask); | ||
| 1845 | FD_SET (inchannel, &non_keyboard_wait_mask); | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | if (inchannel > max_process_desc) | ||
| 1849 | max_process_desc = inchannel; | ||
| 1850 | 2035 | ||
| 1851 | /* This may signal an error. */ | 2036 | /* This may signal an error. */ |
| 1852 | setup_process_coding_systems (process); | 2037 | setup_process_coding_systems (process); |
| @@ -2079,10 +2264,7 @@ create_pty (Lisp_Object process) | |||
| 2079 | pset_status (p, Qrun); | 2264 | pset_status (p, Qrun); |
| 2080 | setup_process_coding_systems (process); | 2265 | setup_process_coding_systems (process); |
| 2081 | 2266 | ||
| 2082 | FD_SET (pty_fd, &input_wait_mask); | 2267 | add_process_read_fd (pty_fd); |
| 2083 | FD_SET (pty_fd, &non_keyboard_wait_mask); | ||
| 2084 | if (pty_fd > max_process_desc) | ||
| 2085 | max_process_desc = pty_fd; | ||
| 2086 | 2268 | ||
| 2087 | pset_tty_name (p, build_string (pty_name)); | 2269 | pset_tty_name (p, build_string (pty_name)); |
| 2088 | } | 2270 | } |
| @@ -2166,8 +2348,8 @@ usage: (make-pipe-process &rest ARGS) */) | |||
| 2166 | p->infd = inchannel; | 2348 | p->infd = inchannel; |
| 2167 | p->outfd = outchannel; | 2349 | p->outfd = outchannel; |
| 2168 | 2350 | ||
| 2169 | if (inchannel > max_process_desc) | 2351 | if (inchannel > max_desc) |
| 2170 | max_process_desc = inchannel; | 2352 | max_desc = inchannel; |
| 2171 | 2353 | ||
| 2172 | buffer = Fplist_get (contact, QCbuffer); | 2354 | buffer = Fplist_get (contact, QCbuffer); |
| 2173 | if (NILP (buffer)) | 2355 | if (NILP (buffer)) |
| @@ -2188,10 +2370,7 @@ usage: (make-pipe-process &rest ARGS) */) | |||
| 2188 | eassert (! p->pty_flag); | 2370 | eassert (! p->pty_flag); |
| 2189 | 2371 | ||
| 2190 | if (!EQ (p->command, Qt)) | 2372 | if (!EQ (p->command, Qt)) |
| 2191 | { | 2373 | add_process_read_fd (inchannel); |
| 2192 | FD_SET (inchannel, &input_wait_mask); | ||
| 2193 | FD_SET (inchannel, &non_keyboard_wait_mask); | ||
| 2194 | } | ||
| 2195 | p->adaptive_read_buffering | 2374 | p->adaptive_read_buffering |
| 2196 | = (NILP (Vprocess_adaptive_read_buffering) ? 0 | 2375 | = (NILP (Vprocess_adaptive_read_buffering) ? 0 |
| 2197 | : EQ (Vprocess_adaptive_read_buffering, Qt) ? 1 : 2); | 2376 | : EQ (Vprocess_adaptive_read_buffering, Qt) ? 1 : 2); |
| @@ -2904,8 +3083,8 @@ usage: (make-serial-process &rest ARGS) */) | |||
| 2904 | p->open_fd[SUBPROCESS_STDIN] = fd; | 3083 | p->open_fd[SUBPROCESS_STDIN] = fd; |
| 2905 | p->infd = fd; | 3084 | p->infd = fd; |
| 2906 | p->outfd = fd; | 3085 | p->outfd = fd; |
| 2907 | if (fd > max_process_desc) | 3086 | if (fd > max_desc) |
| 2908 | max_process_desc = fd; | 3087 | max_desc = fd; |
| 2909 | chan_process[fd] = proc; | 3088 | chan_process[fd] = proc; |
| 2910 | 3089 | ||
| 2911 | buffer = Fplist_get (contact, QCbuffer); | 3090 | buffer = Fplist_get (contact, QCbuffer); |
| @@ -2927,10 +3106,7 @@ usage: (make-serial-process &rest ARGS) */) | |||
| 2927 | eassert (! p->pty_flag); | 3106 | eassert (! p->pty_flag); |
| 2928 | 3107 | ||
| 2929 | if (!EQ (p->command, Qt)) | 3108 | if (!EQ (p->command, Qt)) |
| 2930 | { | 3109 | add_process_read_fd (fd); |
| 2931 | FD_SET (fd, &input_wait_mask); | ||
| 2932 | FD_SET (fd, &non_keyboard_wait_mask); | ||
| 2933 | } | ||
| 2934 | 3110 | ||
| 2935 | if (BUFFERP (buffer)) | 3111 | if (BUFFERP (buffer)) |
| 2936 | { | 3112 | { |
| @@ -3102,7 +3278,7 @@ finish_after_tls_connection (Lisp_Object proc) | |||
| 3102 | pset_status (p, Qfailed); | 3278 | pset_status (p, Qfailed); |
| 3103 | deactivate_process (proc); | 3279 | deactivate_process (proc); |
| 3104 | } | 3280 | } |
| 3105 | else if (! FD_ISSET (p->outfd, &connect_wait_mask)) | 3281 | else if ((fd_callback_info[p->outfd].flags & NON_BLOCKING_CONNECT_FD) == 0) |
| 3106 | { | 3282 | { |
| 3107 | /* If we cleared the connection wait mask before we did the TLS | 3283 | /* If we cleared the connection wait mask before we did the TLS |
| 3108 | setup, then we have to say that the process is finally "open" | 3284 | setup, then we have to say that the process is finally "open" |
| @@ -3412,25 +3588,18 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3412 | if (! (connecting_status (p->status) | 3588 | if (! (connecting_status (p->status) |
| 3413 | && EQ (XCDR (p->status), addrinfos))) | 3589 | && EQ (XCDR (p->status), addrinfos))) |
| 3414 | pset_status (p, Fcons (Qconnect, addrinfos)); | 3590 | pset_status (p, Fcons (Qconnect, addrinfos)); |
| 3415 | if (!FD_ISSET (inch, &connect_wait_mask)) | 3591 | if ((fd_callback_info[inch].flags & NON_BLOCKING_CONNECT_FD) == 0) |
| 3416 | { | 3592 | add_non_blocking_write_fd (inch); |
| 3417 | FD_SET (inch, &connect_wait_mask); | ||
| 3418 | FD_SET (inch, &write_mask); | ||
| 3419 | num_pending_connects++; | ||
| 3420 | } | ||
| 3421 | } | 3593 | } |
| 3422 | else | 3594 | else |
| 3423 | /* A server may have a client filter setting of Qt, but it must | 3595 | /* A server may have a client filter setting of Qt, but it must |
| 3424 | still listen for incoming connects unless it is stopped. */ | 3596 | still listen for incoming connects unless it is stopped. */ |
| 3425 | if ((!EQ (p->filter, Qt) && !EQ (p->command, Qt)) | 3597 | if ((!EQ (p->filter, Qt) && !EQ (p->command, Qt)) |
| 3426 | || (EQ (p->status, Qlisten) && NILP (p->command))) | 3598 | || (EQ (p->status, Qlisten) && NILP (p->command))) |
| 3427 | { | 3599 | add_process_read_fd (inch); |
| 3428 | FD_SET (inch, &input_wait_mask); | ||
| 3429 | FD_SET (inch, &non_keyboard_wait_mask); | ||
| 3430 | } | ||
| 3431 | 3600 | ||
| 3432 | if (inch > max_process_desc) | 3601 | if (inch > max_desc) |
| 3433 | max_process_desc = inch; | 3602 | max_desc = inch; |
| 3434 | 3603 | ||
| 3435 | /* Set up the masks based on the process filter. */ | 3604 | /* Set up the masks based on the process filter. */ |
| 3436 | set_process_filter_masks (p); | 3605 | set_process_filter_masks (p); |
| @@ -4361,26 +4530,11 @@ deactivate_process (Lisp_Object proc) | |||
| 4361 | } | 4530 | } |
| 4362 | #endif | 4531 | #endif |
| 4363 | chan_process[inchannel] = Qnil; | 4532 | chan_process[inchannel] = Qnil; |
| 4364 | FD_CLR (inchannel, &input_wait_mask); | 4533 | delete_read_fd (inchannel); |
| 4365 | FD_CLR (inchannel, &non_keyboard_wait_mask); | 4534 | if ((fd_callback_info[inchannel].flags & NON_BLOCKING_CONNECT_FD) != 0) |
| 4366 | if (FD_ISSET (inchannel, &connect_wait_mask)) | 4535 | delete_write_fd (inchannel); |
| 4367 | { | 4536 | if (inchannel == max_desc) |
| 4368 | FD_CLR (inchannel, &connect_wait_mask); | 4537 | recompute_max_desc (); |
| 4369 | FD_CLR (inchannel, &write_mask); | ||
| 4370 | if (--num_pending_connects < 0) | ||
| 4371 | emacs_abort (); | ||
| 4372 | } | ||
| 4373 | if (inchannel == max_process_desc) | ||
| 4374 | { | ||
| 4375 | /* We just closed the highest-numbered process input descriptor, | ||
| 4376 | so recompute the highest-numbered one now. */ | ||
| 4377 | int i = inchannel; | ||
| 4378 | do | ||
| 4379 | i--; | ||
| 4380 | while (0 <= i && NILP (chan_process[i])); | ||
| 4381 | |||
| 4382 | max_process_desc = i; | ||
| 4383 | } | ||
| 4384 | } | 4538 | } |
| 4385 | } | 4539 | } |
| 4386 | 4540 | ||
| @@ -4409,7 +4563,18 @@ is nil, from any process) before the timeout expired. */) | |||
| 4409 | int nsecs; | 4563 | int nsecs; |
| 4410 | 4564 | ||
| 4411 | if (! NILP (process)) | 4565 | if (! NILP (process)) |
| 4412 | CHECK_PROCESS (process); | 4566 | { |
| 4567 | struct Lisp_Process *procp; | ||
| 4568 | |||
| 4569 | CHECK_PROCESS (process); | ||
| 4570 | procp = XPROCESS (process); | ||
| 4571 | |||
| 4572 | /* Can't wait for a process that is dedicated to a different | ||
| 4573 | thread. */ | ||
| 4574 | if (!EQ (procp->thread, Qnil) && !EQ (procp->thread, Fcurrent_thread ())) | ||
| 4575 | error ("Attempt to accept output from process %s locked to thread %s", | ||
| 4576 | SDATA (procp->name), SDATA (XTHREAD (procp->thread)->name)); | ||
| 4577 | } | ||
| 4413 | else | 4578 | else |
| 4414 | just_this_one = Qnil; | 4579 | just_this_one = Qnil; |
| 4415 | 4580 | ||
| @@ -4627,13 +4792,9 @@ server_accept_connection (Lisp_Object server, int channel) | |||
| 4627 | 4792 | ||
| 4628 | /* Client processes for accepted connections are not stopped initially. */ | 4793 | /* Client processes for accepted connections are not stopped initially. */ |
| 4629 | if (!EQ (p->filter, Qt)) | 4794 | if (!EQ (p->filter, Qt)) |
| 4630 | { | 4795 | add_process_read_fd (s); |
| 4631 | FD_SET (s, &input_wait_mask); | 4796 | if (s > max_desc) |
| 4632 | FD_SET (s, &non_keyboard_wait_mask); | 4797 | max_desc = s; |
| 4633 | } | ||
| 4634 | |||
| 4635 | if (s > max_process_desc) | ||
| 4636 | max_process_desc = s; | ||
| 4637 | 4798 | ||
| 4638 | /* Setup coding system for new process based on server process. | 4799 | /* Setup coding system for new process based on server process. |
| 4639 | This seems to be the proper thing to do, as the coding system | 4800 | This seems to be the proper thing to do, as the coding system |
| @@ -4746,20 +4907,10 @@ wait_for_tls_negotiation (Lisp_Object process) | |||
| 4746 | #endif | 4907 | #endif |
| 4747 | } | 4908 | } |
| 4748 | 4909 | ||
| 4749 | /* This variable is different from waiting_for_input in keyboard.c. | ||
| 4750 | It is used to communicate to a lisp process-filter/sentinel (via the | ||
| 4751 | function Fwaiting_for_user_input_p below) whether Emacs was waiting | ||
| 4752 | for user-input when that process-filter was called. | ||
| 4753 | waiting_for_input cannot be used as that is by definition 0 when | ||
| 4754 | lisp code is being evalled. | ||
| 4755 | This is also used in record_asynch_buffer_change. | ||
| 4756 | For that purpose, this must be 0 | ||
| 4757 | when not inside wait_reading_process_output. */ | ||
| 4758 | static int waiting_for_user_input_p; | ||
| 4759 | |||
| 4760 | static void | 4910 | static void |
| 4761 | wait_reading_process_output_unwind (int data) | 4911 | wait_reading_process_output_unwind (int data) |
| 4762 | { | 4912 | { |
| 4913 | clear_waiting_thread_info (); | ||
| 4763 | waiting_for_user_input_p = data; | 4914 | waiting_for_user_input_p = data; |
| 4764 | } | 4915 | } |
| 4765 | 4916 | ||
| @@ -4832,6 +4983,10 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4832 | /* Close to the current time if known, an invalid timespec otherwise. */ | 4983 | /* Close to the current time if known, an invalid timespec otherwise. */ |
| 4833 | struct timespec now = invalid_timespec (); | 4984 | struct timespec now = invalid_timespec (); |
| 4834 | 4985 | ||
| 4986 | eassert (wait_proc == NULL | ||
| 4987 | || EQ (wait_proc->thread, Qnil) | ||
| 4988 | || XTHREAD (wait_proc->thread) == current_thread); | ||
| 4989 | |||
| 4835 | FD_ZERO (&Available); | 4990 | FD_ZERO (&Available); |
| 4836 | FD_ZERO (&Writeok); | 4991 | FD_ZERO (&Writeok); |
| 4837 | 4992 | ||
| @@ -5004,14 +5159,14 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5004 | if (kbd_on_hold_p ()) | 5159 | if (kbd_on_hold_p ()) |
| 5005 | FD_ZERO (&Atemp); | 5160 | FD_ZERO (&Atemp); |
| 5006 | else | 5161 | else |
| 5007 | Atemp = input_wait_mask; | 5162 | compute_input_wait_mask (&Atemp); |
| 5008 | Ctemp = write_mask; | 5163 | compute_write_mask (&Ctemp); |
| 5009 | 5164 | ||
| 5010 | timeout = make_timespec (0, 0); | 5165 | timeout = make_timespec (0, 0); |
| 5011 | if ((pselect (max (max_process_desc, max_input_desc) + 1, | 5166 | if ((thread_select (pselect, max_desc + 1, |
| 5012 | &Atemp, | 5167 | &Atemp, |
| 5013 | (num_pending_connects > 0 ? &Ctemp : NULL), | 5168 | (num_pending_connects > 0 ? &Ctemp : NULL), |
| 5014 | NULL, &timeout, NULL) | 5169 | NULL, &timeout, NULL) |
| 5015 | <= 0)) | 5170 | <= 0)) |
| 5016 | { | 5171 | { |
| 5017 | /* It's okay for us to do this and then continue with | 5172 | /* It's okay for us to do this and then continue with |
| @@ -5076,17 +5231,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5076 | } | 5231 | } |
| 5077 | else if (!NILP (wait_for_cell)) | 5232 | else if (!NILP (wait_for_cell)) |
| 5078 | { | 5233 | { |
| 5079 | Available = non_process_wait_mask; | 5234 | compute_non_process_wait_mask (&Available); |
| 5080 | check_delay = 0; | 5235 | check_delay = 0; |
| 5081 | check_write = 0; | 5236 | check_write = 0; |
| 5082 | } | 5237 | } |
| 5083 | else | 5238 | else |
| 5084 | { | 5239 | { |
| 5085 | if (! read_kbd) | 5240 | if (! read_kbd) |
| 5086 | Available = non_keyboard_wait_mask; | 5241 | compute_non_keyboard_wait_mask (&Available); |
| 5087 | else | 5242 | else |
| 5088 | Available = input_wait_mask; | 5243 | compute_input_wait_mask (&Available); |
| 5089 | Writeok = write_mask; | 5244 | compute_write_mask (&Writeok); |
| 5090 | check_delay = wait_proc ? 0 : process_output_delay_count; | 5245 | check_delay = wait_proc ? 0 : process_output_delay_count; |
| 5091 | check_write = true; | 5246 | check_write = true; |
| 5092 | } | 5247 | } |
| @@ -5128,7 +5283,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5128 | int adaptive_nsecs = timeout.tv_nsec; | 5283 | int adaptive_nsecs = timeout.tv_nsec; |
| 5129 | if (timeout.tv_sec > 0 || adaptive_nsecs > READ_OUTPUT_DELAY_MAX) | 5284 | if (timeout.tv_sec > 0 || adaptive_nsecs > READ_OUTPUT_DELAY_MAX) |
| 5130 | adaptive_nsecs = READ_OUTPUT_DELAY_MAX; | 5285 | adaptive_nsecs = READ_OUTPUT_DELAY_MAX; |
| 5131 | for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++) | 5286 | for (channel = 0; check_delay > 0 && channel <= max_desc; channel++) |
| 5132 | { | 5287 | { |
| 5133 | proc = chan_process[channel]; | 5288 | proc = chan_process[channel]; |
| 5134 | if (NILP (proc)) | 5289 | if (NILP (proc)) |
| @@ -5187,17 +5342,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5187 | } | 5342 | } |
| 5188 | #endif | 5343 | #endif |
| 5189 | 5344 | ||
| 5345 | nfds = thread_select ( | ||
| 5190 | #if defined (HAVE_NS) | 5346 | #if defined (HAVE_NS) |
| 5191 | nfds = ns_select | 5347 | ns_select |
| 5192 | #elif defined (HAVE_GLIB) | 5348 | #elif defined (HAVE_GLIB) |
| 5193 | nfds = xg_select | 5349 | xg_select |
| 5194 | #else | 5350 | #else |
| 5195 | nfds = pselect | 5351 | pselect |
| 5196 | #endif | 5352 | #endif |
| 5197 | (max (max_process_desc, max_input_desc) + 1, | 5353 | , max_desc + 1, |
| 5198 | &Available, | 5354 | &Available, |
| 5199 | (check_write ? &Writeok : 0), | 5355 | (check_write ? &Writeok : 0), |
| 5200 | NULL, &timeout, NULL); | 5356 | NULL, &timeout, NULL); |
| 5201 | 5357 | ||
| 5202 | #ifdef HAVE_GNUTLS | 5358 | #ifdef HAVE_GNUTLS |
| 5203 | /* GnuTLS buffers data internally. In lowat mode it leaves | 5359 | /* GnuTLS buffers data internally. In lowat mode it leaves |
| @@ -5381,22 +5537,22 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5381 | if (no_avail || nfds == 0) | 5537 | if (no_avail || nfds == 0) |
| 5382 | continue; | 5538 | continue; |
| 5383 | 5539 | ||
| 5384 | for (channel = 0; channel <= max_input_desc; ++channel) | 5540 | for (channel = 0; channel <= max_desc; ++channel) |
| 5385 | { | 5541 | { |
| 5386 | struct fd_callback_data *d = &fd_callback_info[channel]; | 5542 | struct fd_callback_data *d = &fd_callback_info[channel]; |
| 5387 | if (d->func | 5543 | if (d->func |
| 5388 | && ((d->condition & FOR_READ | 5544 | && ((d->flags & FOR_READ |
| 5389 | && FD_ISSET (channel, &Available)) | 5545 | && FD_ISSET (channel, &Available)) |
| 5390 | || (d->condition & FOR_WRITE | 5546 | || ((d->flags & FOR_WRITE) |
| 5391 | && FD_ISSET (channel, &write_mask)))) | 5547 | && FD_ISSET (channel, &Writeok)))) |
| 5392 | d->func (channel, d->data); | 5548 | d->func (channel, d->data); |
| 5393 | } | 5549 | } |
| 5394 | 5550 | ||
| 5395 | for (channel = 0; channel <= max_process_desc; channel++) | 5551 | for (channel = 0; channel <= max_desc; channel++) |
| 5396 | { | 5552 | { |
| 5397 | if (FD_ISSET (channel, &Available) | 5553 | if (FD_ISSET (channel, &Available) |
| 5398 | && FD_ISSET (channel, &non_keyboard_wait_mask) | 5554 | && ((fd_callback_info[channel].flags & (KEYBOARD_FD | PROCESS_FD)) |
| 5399 | && !FD_ISSET (channel, &non_process_wait_mask)) | 5555 | == PROCESS_FD)) |
| 5400 | { | 5556 | { |
| 5401 | int nread; | 5557 | int nread; |
| 5402 | 5558 | ||
| @@ -5461,8 +5617,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5461 | 5617 | ||
| 5462 | /* Clear the descriptor now, so we only raise the | 5618 | /* Clear the descriptor now, so we only raise the |
| 5463 | signal once. */ | 5619 | signal once. */ |
| 5464 | FD_CLR (channel, &input_wait_mask); | 5620 | delete_read_fd (channel); |
| 5465 | FD_CLR (channel, &non_keyboard_wait_mask); | ||
| 5466 | 5621 | ||
| 5467 | if (p->pid == -2) | 5622 | if (p->pid == -2) |
| 5468 | { | 5623 | { |
| @@ -5501,14 +5656,12 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5501 | } | 5656 | } |
| 5502 | } | 5657 | } |
| 5503 | if (FD_ISSET (channel, &Writeok) | 5658 | if (FD_ISSET (channel, &Writeok) |
| 5504 | && FD_ISSET (channel, &connect_wait_mask)) | 5659 | && (fd_callback_info[channel].flags |
| 5660 | & NON_BLOCKING_CONNECT_FD) != 0) | ||
| 5505 | { | 5661 | { |
| 5506 | struct Lisp_Process *p; | 5662 | struct Lisp_Process *p; |
| 5507 | 5663 | ||
| 5508 | FD_CLR (channel, &connect_wait_mask); | 5664 | delete_write_fd (channel); |
| 5509 | FD_CLR (channel, &write_mask); | ||
| 5510 | if (--num_pending_connects < 0) | ||
| 5511 | emacs_abort (); | ||
| 5512 | 5665 | ||
| 5513 | proc = chan_process[channel]; | 5666 | proc = chan_process[channel]; |
| 5514 | if (NILP (proc)) | 5667 | if (NILP (proc)) |
| @@ -5576,10 +5729,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5576 | 5729 | ||
| 5577 | if (0 <= p->infd && !EQ (p->filter, Qt) | 5730 | if (0 <= p->infd && !EQ (p->filter, Qt) |
| 5578 | && !EQ (p->command, Qt)) | 5731 | && !EQ (p->command, Qt)) |
| 5579 | { | 5732 | add_process_read_fd (p->infd); |
| 5580 | FD_SET (p->infd, &input_wait_mask); | ||
| 5581 | FD_SET (p->infd, &non_keyboard_wait_mask); | ||
| 5582 | } | ||
| 5583 | } | 5733 | } |
| 5584 | } | 5734 | } |
| 5585 | } /* End for each file descriptor. */ | 5735 | } /* End for each file descriptor. */ |
| @@ -6550,10 +6700,7 @@ of incoming traffic. */) | |||
| 6550 | p = XPROCESS (process); | 6700 | p = XPROCESS (process); |
| 6551 | if (NILP (p->command) | 6701 | if (NILP (p->command) |
| 6552 | && p->infd >= 0) | 6702 | && p->infd >= 0) |
| 6553 | { | 6703 | delete_read_fd (p->infd); |
| 6554 | FD_CLR (p->infd, &input_wait_mask); | ||
| 6555 | FD_CLR (p->infd, &non_keyboard_wait_mask); | ||
| 6556 | } | ||
| 6557 | pset_command (p, Qt); | 6704 | pset_command (p, Qt); |
| 6558 | return process; | 6705 | return process; |
| 6559 | } | 6706 | } |
| @@ -6582,8 +6729,7 @@ traffic. */) | |||
| 6582 | && p->infd >= 0 | 6729 | && p->infd >= 0 |
| 6583 | && (!EQ (p->filter, Qt) || EQ (p->status, Qlisten))) | 6730 | && (!EQ (p->filter, Qt) || EQ (p->status, Qlisten))) |
| 6584 | { | 6731 | { |
| 6585 | FD_SET (p->infd, &input_wait_mask); | 6732 | add_process_read_fd (p->infd); |
| 6586 | FD_SET (p->infd, &non_keyboard_wait_mask); | ||
| 6587 | #ifdef WINDOWSNT | 6733 | #ifdef WINDOWSNT |
| 6588 | if (fd_info[ p->infd ].flags & FILE_SERIAL) | 6734 | if (fd_info[ p->infd ].flags & FILE_SERIAL) |
| 6589 | PurgeComm (fd_info[ p->infd ].hnd, PURGE_RXABORT | PURGE_RXCLEAR); | 6735 | PurgeComm (fd_info[ p->infd ].hnd, PURGE_RXABORT | PURGE_RXCLEAR); |
| @@ -6890,10 +7036,7 @@ handle_child_signal (int sig) | |||
| 6890 | 7036 | ||
| 6891 | /* clear_desc_flag avoids a compiler bug in Microsoft C. */ | 7037 | /* clear_desc_flag avoids a compiler bug in Microsoft C. */ |
| 6892 | if (clear_desc_flag) | 7038 | if (clear_desc_flag) |
| 6893 | { | 7039 | delete_read_fd (p->infd); |
| 6894 | FD_CLR (p->infd, &input_wait_mask); | ||
| 6895 | FD_CLR (p->infd, &non_keyboard_wait_mask); | ||
| 6896 | } | ||
| 6897 | } | 7040 | } |
| 6898 | } | 7041 | } |
| 6899 | } | 7042 | } |
| @@ -7253,9 +7396,10 @@ keyboard_bit_set (fd_set *mask) | |||
| 7253 | { | 7396 | { |
| 7254 | int fd; | 7397 | int fd; |
| 7255 | 7398 | ||
| 7256 | for (fd = 0; fd <= max_input_desc; fd++) | 7399 | for (fd = 0; fd <= max_desc; fd++) |
| 7257 | if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask) | 7400 | if (FD_ISSET (fd, mask) |
| 7258 | && !FD_ISSET (fd, &non_keyboard_wait_mask)) | 7401 | && ((fd_callback_info[fd].flags & (FOR_READ | KEYBOARD_FD)) |
| 7402 | == (FOR_READ | KEYBOARD_FD))) | ||
| 7259 | return 1; | 7403 | return 1; |
| 7260 | 7404 | ||
| 7261 | return 0; | 7405 | return 0; |
| @@ -7492,14 +7636,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 7492 | void | 7636 | void |
| 7493 | add_timer_wait_descriptor (int fd) | 7637 | add_timer_wait_descriptor (int fd) |
| 7494 | { | 7638 | { |
| 7495 | FD_SET (fd, &input_wait_mask); | 7639 | add_read_fd (fd, timerfd_callback, NULL); |
| 7496 | FD_SET (fd, &non_keyboard_wait_mask); | 7640 | fd_callback_info[fd].flags &= ~KEYBOARD_FD; |
| 7497 | FD_SET (fd, &non_process_wait_mask); | ||
| 7498 | fd_callback_info[fd].func = timerfd_callback; | ||
| 7499 | fd_callback_info[fd].data = NULL; | ||
| 7500 | fd_callback_info[fd].condition |= FOR_READ; | ||
| 7501 | if (fd > max_input_desc) | ||
| 7502 | max_input_desc = fd; | ||
| 7503 | } | 7641 | } |
| 7504 | 7642 | ||
| 7505 | #endif /* HAVE_TIMERFD */ | 7643 | #endif /* HAVE_TIMERFD */ |
| @@ -7523,10 +7661,11 @@ void | |||
| 7523 | add_keyboard_wait_descriptor (int desc) | 7661 | add_keyboard_wait_descriptor (int desc) |
| 7524 | { | 7662 | { |
| 7525 | #ifdef subprocesses /* Actually means "not MSDOS". */ | 7663 | #ifdef subprocesses /* Actually means "not MSDOS". */ |
| 7526 | FD_SET (desc, &input_wait_mask); | 7664 | eassert (desc >= 0 && desc < FD_SETSIZE); |
| 7527 | FD_SET (desc, &non_process_wait_mask); | 7665 | fd_callback_info[desc].flags &= ~PROCESS_FD; |
| 7528 | if (desc > max_input_desc) | 7666 | fd_callback_info[desc].flags |= (FOR_READ | KEYBOARD_FD); |
| 7529 | max_input_desc = desc; | 7667 | if (desc > max_desc) |
| 7668 | max_desc = desc; | ||
| 7530 | #endif | 7669 | #endif |
| 7531 | } | 7670 | } |
| 7532 | 7671 | ||
| @@ -7536,9 +7675,12 @@ void | |||
| 7536 | delete_keyboard_wait_descriptor (int desc) | 7675 | delete_keyboard_wait_descriptor (int desc) |
| 7537 | { | 7676 | { |
| 7538 | #ifdef subprocesses | 7677 | #ifdef subprocesses |
| 7539 | FD_CLR (desc, &input_wait_mask); | 7678 | eassert (desc >= 0 && desc < FD_SETSIZE); |
| 7540 | FD_CLR (desc, &non_process_wait_mask); | 7679 | |
| 7541 | delete_input_desc (desc); | 7680 | fd_callback_info[desc].flags &= ~(FOR_READ | KEYBOARD_FD | PROCESS_FD); |
| 7681 | |||
| 7682 | if (desc == max_desc) | ||
| 7683 | recompute_max_desc (); | ||
| 7542 | #endif | 7684 | #endif |
| 7543 | } | 7685 | } |
| 7544 | 7686 | ||
| @@ -7819,15 +7961,10 @@ init_process_emacs (int sockfd) | |||
| 7819 | } | 7961 | } |
| 7820 | #endif | 7962 | #endif |
| 7821 | 7963 | ||
| 7822 | FD_ZERO (&input_wait_mask); | ||
| 7823 | FD_ZERO (&non_keyboard_wait_mask); | ||
| 7824 | FD_ZERO (&non_process_wait_mask); | ||
| 7825 | FD_ZERO (&write_mask); | ||
| 7826 | max_process_desc = max_input_desc = -1; | ||
| 7827 | external_sock_fd = sockfd; | 7964 | external_sock_fd = sockfd; |
| 7965 | max_desc = -1; | ||
| 7828 | memset (fd_callback_info, 0, sizeof (fd_callback_info)); | 7966 | memset (fd_callback_info, 0, sizeof (fd_callback_info)); |
| 7829 | 7967 | ||
| 7830 | FD_ZERO (&connect_wait_mask); | ||
| 7831 | num_pending_connects = 0; | 7968 | num_pending_connects = 0; |
| 7832 | 7969 | ||
| 7833 | process_output_delay_count = 0; | 7970 | process_output_delay_count = 0; |
| @@ -8027,6 +8164,8 @@ The variable takes effect when `start-process' is called. */); | |||
| 8027 | defsubr (&Sprocess_filter); | 8164 | defsubr (&Sprocess_filter); |
| 8028 | defsubr (&Sset_process_sentinel); | 8165 | defsubr (&Sset_process_sentinel); |
| 8029 | defsubr (&Sprocess_sentinel); | 8166 | defsubr (&Sprocess_sentinel); |
| 8167 | defsubr (&Sset_process_thread); | ||
| 8168 | defsubr (&Sprocess_thread); | ||
| 8030 | defsubr (&Sset_process_window_size); | 8169 | defsubr (&Sset_process_window_size); |
| 8031 | defsubr (&Sset_process_inherit_coding_system_flag); | 8170 | defsubr (&Sset_process_inherit_coding_system_flag); |
| 8032 | defsubr (&Sset_process_query_on_exit_flag); | 8171 | defsubr (&Sset_process_query_on_exit_flag); |