diff options
| author | Tom Tromey | 2012-08-15 13:19:24 -0600 |
|---|---|---|
| committer | Tom Tromey | 2012-08-15 13:19:24 -0600 |
| commit | 6c0d5ae50789673f53c834084bbe1f62f5a62731 (patch) | |
| tree | 0f976b74b292b2a4714470eebb2ce39548d47678 /src | |
| parent | aa14ccd1e2edec2735f9200a4f2e5eee3b0abe09 (diff) | |
| download | emacs-6c0d5ae50789673f53c834084bbe1f62f5a62731.tar.gz emacs-6c0d5ae50789673f53c834084bbe1f62f5a62731.zip | |
process changes
This changes wait_reading_process_output to handle threads better. It
introduces a wrapper for select that releases the global lock, and it
ensures that only a single thread can select a given file descriptor
at a time.
This also adds the thread-locking feature to processes. By default a
process can only have its output accepted by the thread that created
it. This can be changed using set-process-thread. (If the thread
exits, the process is again available for waiting by any thread.)
Note that thread-signal will not currently interrupt a thread blocked
on select. I'll fix this later.
Diffstat (limited to 'src')
| -rw-r--r-- | src/process.c | 175 | ||||
| -rw-r--r-- | src/process.h | 5 | ||||
| -rw-r--r-- | src/thread.c | 47 | ||||
| -rw-r--r-- | src/thread.h | 22 |
4 files changed, 221 insertions, 28 deletions
diff --git a/src/process.c b/src/process.c index 0d3355512b8..ada673e3c34 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -335,6 +335,13 @@ static struct fd_callback_data | |||
| 335 | void *data; | 335 | void *data; |
| 336 | /* Flags from enum fd_bits. */ | 336 | /* Flags from enum fd_bits. */ |
| 337 | int flags; | 337 | int flags; |
| 338 | /* If this fd is locked to a certain thread, this points to it. | ||
| 339 | Otherwise, this is NULL. If an fd is locked to a thread, then | ||
| 340 | only that thread is permitted to wait on it. */ | ||
| 341 | struct thread_state *thread; | ||
| 342 | /* If this fd is currently being selected on by a thread, this | ||
| 343 | points to the thread. Otherwise it is NULL. */ | ||
| 344 | struct thread_state *waiting_thread; | ||
| 338 | } fd_callback_info[MAXDESC]; | 345 | } fd_callback_info[MAXDESC]; |
| 339 | 346 | ||
| 340 | 347 | ||
| @@ -451,8 +458,17 @@ compute_input_wait_mask (SELECT_TYPE *mask) | |||
| 451 | FD_ZERO (mask); | 458 | FD_ZERO (mask); |
| 452 | for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd) | 459 | for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd) |
| 453 | { | 460 | { |
| 461 | if (fd_callback_info[fd].thread != NULL | ||
| 462 | && fd_callback_info[fd].thread != current_thread) | ||
| 463 | continue; | ||
| 464 | if (fd_callback_info[fd].waiting_thread != NULL | ||
| 465 | && fd_callback_info[fd].waiting_thread != current_thread) | ||
| 466 | continue; | ||
| 454 | if ((fd_callback_info[fd].flags & FOR_READ) != 0) | 467 | if ((fd_callback_info[fd].flags & FOR_READ) != 0) |
| 455 | FD_SET (fd, mask); | 468 | { |
| 469 | FD_SET (fd, mask); | ||
| 470 | fd_callback_info[fd].waiting_thread = current_thread; | ||
| 471 | } | ||
| 456 | } | 472 | } |
| 457 | } | 473 | } |
| 458 | 474 | ||
| @@ -464,9 +480,18 @@ compute_non_process_wait_mask (SELECT_TYPE *mask) | |||
| 464 | FD_ZERO (mask); | 480 | FD_ZERO (mask); |
| 465 | for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd) | 481 | for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd) |
| 466 | { | 482 | { |
| 483 | if (fd_callback_info[fd].thread != NULL | ||
| 484 | && fd_callback_info[fd].thread != current_thread) | ||
| 485 | continue; | ||
| 486 | if (fd_callback_info[fd].waiting_thread != NULL | ||
| 487 | && fd_callback_info[fd].waiting_thread != current_thread) | ||
| 488 | continue; | ||
| 467 | if ((fd_callback_info[fd].flags & FOR_READ) != 0 | 489 | if ((fd_callback_info[fd].flags & FOR_READ) != 0 |
| 468 | && (fd_callback_info[fd].flags & PROCESS_FD) == 0) | 490 | && (fd_callback_info[fd].flags & PROCESS_FD) == 0) |
| 469 | FD_SET (fd, mask); | 491 | { |
| 492 | FD_SET (fd, mask); | ||
| 493 | fd_callback_info[fd].waiting_thread = current_thread; | ||
| 494 | } | ||
| 470 | } | 495 | } |
| 471 | } | 496 | } |
| 472 | 497 | ||
| @@ -478,9 +503,18 @@ compute_non_keyboard_wait_mask (SELECT_TYPE *mask) | |||
| 478 | FD_ZERO (mask); | 503 | FD_ZERO (mask); |
| 479 | for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd) | 504 | for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd) |
| 480 | { | 505 | { |
| 506 | if (fd_callback_info[fd].thread != NULL | ||
| 507 | && fd_callback_info[fd].thread != current_thread) | ||
| 508 | continue; | ||
| 509 | if (fd_callback_info[fd].waiting_thread != NULL | ||
| 510 | && fd_callback_info[fd].waiting_thread != current_thread) | ||
| 511 | continue; | ||
| 481 | if ((fd_callback_info[fd].flags & FOR_READ) != 0 | 512 | if ((fd_callback_info[fd].flags & FOR_READ) != 0 |
| 482 | && (fd_callback_info[fd].flags & KEYBOARD_FD) == 0) | 513 | && (fd_callback_info[fd].flags & KEYBOARD_FD) == 0) |
| 483 | FD_SET (fd, mask); | 514 | { |
| 515 | FD_SET (fd, mask); | ||
| 516 | fd_callback_info[fd].waiting_thread = current_thread; | ||
| 517 | } | ||
| 484 | } | 518 | } |
| 485 | } | 519 | } |
| 486 | 520 | ||
| @@ -492,12 +526,31 @@ compute_write_mask (SELECT_TYPE *mask) | |||
| 492 | FD_ZERO (mask); | 526 | FD_ZERO (mask); |
| 493 | for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd) | 527 | for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd) |
| 494 | { | 528 | { |
| 529 | if (fd_callback_info[fd].thread != NULL | ||
| 530 | && fd_callback_info[fd].thread != current_thread) | ||
| 531 | continue; | ||
| 532 | if (fd_callback_info[fd].waiting_thread != NULL | ||
| 533 | && fd_callback_info[fd].waiting_thread != current_thread) | ||
| 534 | continue; | ||
| 495 | if ((fd_callback_info[fd].flags & FOR_WRITE) != 0) | 535 | if ((fd_callback_info[fd].flags & FOR_WRITE) != 0) |
| 496 | FD_SET (fd, mask); | 536 | { |
| 537 | FD_SET (fd, mask); | ||
| 538 | fd_callback_info[fd].waiting_thread = current_thread; | ||
| 539 | } | ||
| 497 | } | 540 | } |
| 498 | } | 541 | } |
| 499 | 542 | ||
| 543 | static void | ||
| 544 | clear_waiting_thread_info (void) | ||
| 545 | { | ||
| 546 | int fd; | ||
| 500 | 547 | ||
| 548 | for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd) | ||
| 549 | { | ||
| 550 | if (fd_callback_info[fd].waiting_thread == current_thread) | ||
| 551 | fd_callback_info[fd].waiting_thread = NULL; | ||
| 552 | } | ||
| 553 | } | ||
| 501 | 554 | ||
| 502 | 555 | ||
| 503 | /* Compute the Lisp form of the process status, p->status, from | 556 | /* Compute the Lisp form of the process status, p->status, from |
| @@ -709,6 +762,7 @@ make_process (Lisp_Object name) | |||
| 709 | Lisp data to nil, so do it only for slots which should not be nil. */ | 762 | Lisp data to nil, so do it only for slots which should not be nil. */ |
| 710 | PSET (p, status, Qrun); | 763 | PSET (p, status, Qrun); |
| 711 | PSET (p, mark, Fmake_marker ()); | 764 | PSET (p, mark, Fmake_marker ()); |
| 765 | PSET (p, thread, Fcurrent_thread ()); | ||
| 712 | 766 | ||
| 713 | /* Initialize non-Lisp data. Note that allocate_process zeroes out all | 767 | /* Initialize non-Lisp data. Note that allocate_process zeroes out all |
| 714 | non-Lisp data, so do it only for slots which should not be zero. */ | 768 | non-Lisp data, so do it only for slots which should not be zero. */ |
| @@ -746,6 +800,27 @@ remove_process (register Lisp_Object proc) | |||
| 746 | deactivate_process (proc); | 800 | deactivate_process (proc); |
| 747 | } | 801 | } |
| 748 | 802 | ||
| 803 | void | ||
| 804 | update_processes_for_thread_death (Lisp_Object dying_thread) | ||
| 805 | { | ||
| 806 | Lisp_Object pair; | ||
| 807 | |||
| 808 | for (pair = Vprocess_alist; !NILP (pair); pair = XCDR (pair)) | ||
| 809 | { | ||
| 810 | Lisp_Object process = XCDR (XCAR (pair)); | ||
| 811 | if (EQ (XPROCESS (process)->thread, dying_thread)) | ||
| 812 | { | ||
| 813 | struct Lisp_Process *proc = XPROCESS (process); | ||
| 814 | |||
| 815 | proc->thread = Qnil; | ||
| 816 | if (proc->infd >= 0) | ||
| 817 | fd_callback_info[proc->infd].thread = NULL; | ||
| 818 | if (proc->outfd >= 0) | ||
| 819 | fd_callback_info[proc->outfd].thread = NULL; | ||
| 820 | } | ||
| 821 | } | ||
| 822 | } | ||
| 823 | |||
| 749 | 824 | ||
| 750 | DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0, | 825 | DEFUN ("processp", Fprocessp, Sprocessp, 1, 1, 0, |
| 751 | doc: /* Return t if OBJECT is a process. */) | 826 | doc: /* Return t if OBJECT is a process. */) |
| @@ -1094,6 +1169,42 @@ See `set-process-sentinel' for more info on sentinels. */) | |||
| 1094 | return XPROCESS (process)->sentinel; | 1169 | return XPROCESS (process)->sentinel; |
| 1095 | } | 1170 | } |
| 1096 | 1171 | ||
| 1172 | DEFUN ("set-process-thread", Fset_process_thread, Sset_process_thread, | ||
| 1173 | 2, 2, 0, | ||
| 1174 | doc: /* FIXME */) | ||
| 1175 | (Lisp_Object process, Lisp_Object thread) | ||
| 1176 | { | ||
| 1177 | struct Lisp_Process *proc; | ||
| 1178 | struct thread_state *tstate; | ||
| 1179 | |||
| 1180 | CHECK_PROCESS (process); | ||
| 1181 | if (NILP (thread)) | ||
| 1182 | tstate = NULL; | ||
| 1183 | else | ||
| 1184 | { | ||
| 1185 | CHECK_THREAD (thread); | ||
| 1186 | tstate = XTHREAD (thread); | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | proc = XPROCESS (process); | ||
| 1190 | proc->thread = thread; | ||
| 1191 | if (proc->infd >= 0) | ||
| 1192 | fd_callback_info[proc->infd].thread = tstate; | ||
| 1193 | if (proc->outfd >= 0) | ||
| 1194 | fd_callback_info[proc->outfd].thread = tstate; | ||
| 1195 | |||
| 1196 | return thread; | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | DEFUN ("process-thread", Fprocess_thread, Sprocess_thread, | ||
| 1200 | 1, 1, 0, | ||
| 1201 | doc: /* FIXME */) | ||
| 1202 | (Lisp_Object process) | ||
| 1203 | { | ||
| 1204 | CHECK_PROCESS (process); | ||
| 1205 | return XPROCESS (process)->thread; | ||
| 1206 | } | ||
| 1207 | |||
| 1097 | DEFUN ("set-process-window-size", Fset_process_window_size, | 1208 | DEFUN ("set-process-window-size", Fset_process_window_size, |
| 1098 | Sset_process_window_size, 3, 3, 0, | 1209 | Sset_process_window_size, 3, 3, 0, |
| 1099 | doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */) | 1210 | doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */) |
| @@ -3993,7 +4104,17 @@ Return non-nil if we received any output before the timeout expired. */) | |||
| 3993 | int nsecs; | 4104 | int nsecs; |
| 3994 | 4105 | ||
| 3995 | if (! NILP (process)) | 4106 | if (! NILP (process)) |
| 3996 | CHECK_PROCESS (process); | 4107 | { |
| 4108 | struct Lisp_Process *procp; | ||
| 4109 | |||
| 4110 | CHECK_PROCESS (process); | ||
| 4111 | procp = XPROCESS (process); | ||
| 4112 | |||
| 4113 | /* Can't wait for a process that is dedicated to a different | ||
| 4114 | thread. */ | ||
| 4115 | if (!EQ (procp->thread, Qnil) && !EQ (procp->thread, Fcurrent_thread ())) | ||
| 4116 | error ("FIXME"); | ||
| 4117 | } | ||
| 3997 | else | 4118 | else |
| 3998 | just_this_one = Qnil; | 4119 | just_this_one = Qnil; |
| 3999 | 4120 | ||
| @@ -4249,20 +4370,10 @@ server_accept_connection (Lisp_Object server, int channel) | |||
| 4249 | build_string ("\n"))); | 4370 | build_string ("\n"))); |
| 4250 | } | 4371 | } |
| 4251 | 4372 | ||
| 4252 | /* This variable is different from waiting_for_input in keyboard.c. | ||
| 4253 | It is used to communicate to a lisp process-filter/sentinel (via the | ||
| 4254 | function Fwaiting_for_user_input_p below) whether Emacs was waiting | ||
| 4255 | for user-input when that process-filter was called. | ||
| 4256 | waiting_for_input cannot be used as that is by definition 0 when | ||
| 4257 | lisp code is being evalled. | ||
| 4258 | This is also used in record_asynch_buffer_change. | ||
| 4259 | For that purpose, this must be 0 | ||
| 4260 | when not inside wait_reading_process_output. */ | ||
| 4261 | static int waiting_for_user_input_p; | ||
| 4262 | |||
| 4263 | static Lisp_Object | 4373 | static Lisp_Object |
| 4264 | wait_reading_process_output_unwind (Lisp_Object data) | 4374 | wait_reading_process_output_unwind (Lisp_Object data) |
| 4265 | { | 4375 | { |
| 4376 | clear_waiting_thread_info (); | ||
| 4266 | waiting_for_user_input_p = XINT (data); | 4377 | waiting_for_user_input_p = XINT (data); |
| 4267 | return Qnil; | 4378 | return Qnil; |
| 4268 | } | 4379 | } |
| @@ -4329,6 +4440,10 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4329 | int got_some_input = 0; | 4440 | int got_some_input = 0; |
| 4330 | ptrdiff_t count = SPECPDL_INDEX (); | 4441 | ptrdiff_t count = SPECPDL_INDEX (); |
| 4331 | 4442 | ||
| 4443 | eassert (wait_proc == NULL | ||
| 4444 | || EQ (wait_proc->thread, Qnil) | ||
| 4445 | || XTHREAD (wait_proc->thread) == current_thread); | ||
| 4446 | |||
| 4332 | FD_ZERO (&Available); | 4447 | FD_ZERO (&Available); |
| 4333 | FD_ZERO (&Writeok); | 4448 | FD_ZERO (&Writeok); |
| 4334 | 4449 | ||
| @@ -4484,14 +4599,15 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4484 | compute_write_mask (&Ctemp); | 4599 | compute_write_mask (&Ctemp); |
| 4485 | 4600 | ||
| 4486 | timeout = make_emacs_time (0, 0); | 4601 | timeout = make_emacs_time (0, 0); |
| 4487 | if ((pselect (max (max_process_desc, max_input_desc) + 1, | 4602 | if ((thread_select (pselect, |
| 4488 | &Atemp, | 4603 | max (max_process_desc, max_input_desc) + 1, |
| 4604 | &Atemp, | ||
| 4489 | #ifdef NON_BLOCKING_CONNECT | 4605 | #ifdef NON_BLOCKING_CONNECT |
| 4490 | (num_pending_connects > 0 ? &Ctemp : NULL), | 4606 | (num_pending_connects > 0 ? &Ctemp : NULL), |
| 4491 | #else | 4607 | #else |
| 4492 | NULL, | 4608 | NULL, |
| 4493 | #endif | 4609 | #endif |
| 4494 | NULL, &timeout, NULL) | 4610 | NULL, &timeout, NULL) |
| 4495 | <= 0)) | 4611 | <= 0)) |
| 4496 | { | 4612 | { |
| 4497 | /* It's okay for us to do this and then continue with | 4613 | /* It's okay for us to do this and then continue with |
| @@ -4639,17 +4755,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4639 | process_output_skip = 0; | 4755 | process_output_skip = 0; |
| 4640 | } | 4756 | } |
| 4641 | #endif | 4757 | #endif |
| 4758 | nfds = thread_select ( | ||
| 4642 | #if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS) | 4759 | #if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS) |
| 4643 | nfds = xg_select | 4760 | xg_select |
| 4644 | #elif defined (HAVE_NS) | 4761 | #elif defined (HAVE_NS) |
| 4645 | nfds = ns_select | 4762 | ns_select |
| 4646 | #else | 4763 | #else |
| 4647 | nfds = pselect | 4764 | pselect |
| 4648 | #endif | 4765 | #endif |
| 4649 | (max (max_process_desc, max_input_desc) + 1, | 4766 | , max (max_process_desc, max_input_desc) + 1, |
| 4650 | &Available, | 4767 | &Available, |
| 4651 | (check_write ? &Writeok : (SELECT_TYPE *)0), | 4768 | (check_write ? &Writeok : (SELECT_TYPE *)0), |
| 4652 | NULL, &timeout, NULL); | 4769 | NULL, &timeout, NULL); |
| 4653 | 4770 | ||
| 4654 | #ifdef HAVE_GNUTLS | 4771 | #ifdef HAVE_GNUTLS |
| 4655 | /* GnuTLS buffers data internally. In lowat mode it leaves | 4772 | /* GnuTLS buffers data internally. In lowat mode it leaves |
| @@ -7597,6 +7714,8 @@ The variable takes effect when `start-process' is called. */); | |||
| 7597 | defsubr (&Sprocess_filter); | 7714 | defsubr (&Sprocess_filter); |
| 7598 | defsubr (&Sset_process_sentinel); | 7715 | defsubr (&Sset_process_sentinel); |
| 7599 | defsubr (&Sprocess_sentinel); | 7716 | defsubr (&Sprocess_sentinel); |
| 7717 | defsubr (&Sset_process_thread); | ||
| 7718 | defsubr (&Sprocess_thread); | ||
| 7600 | defsubr (&Sset_process_window_size); | 7719 | defsubr (&Sset_process_window_size); |
| 7601 | defsubr (&Sset_process_inherit_coding_system_flag); | 7720 | defsubr (&Sset_process_inherit_coding_system_flag); |
| 7602 | defsubr (&Sset_process_query_on_exit_flag); | 7721 | defsubr (&Sset_process_query_on_exit_flag); |
diff --git a/src/process.h b/src/process.h index 43cc7ea33c0..1ddfe915357 100644 --- a/src/process.h +++ b/src/process.h | |||
| @@ -103,6 +103,9 @@ struct Lisp_Process | |||
| 103 | Lisp_Object gnutls_cred_type; | 103 | Lisp_Object gnutls_cred_type; |
| 104 | #endif | 104 | #endif |
| 105 | 105 | ||
| 106 | /* The thread a process is linked to, or nil for any thread. */ | ||
| 107 | Lisp_Object thread; | ||
| 108 | |||
| 106 | /* After this point, there are no Lisp_Objects any more. */ | 109 | /* After this point, there are no Lisp_Objects any more. */ |
| 107 | /* alloc.c assumes that `pid' is the first such non-Lisp slot. */ | 110 | /* alloc.c assumes that `pid' is the first such non-Lisp slot. */ |
| 108 | 111 | ||
| @@ -208,3 +211,5 @@ extern void add_read_fd (int fd, fd_callback func, void *data); | |||
| 208 | extern void delete_read_fd (int fd); | 211 | extern void delete_read_fd (int fd); |
| 209 | extern void add_write_fd (int fd, fd_callback func, void *data); | 212 | extern void add_write_fd (int fd, fd_callback func, void *data); |
| 210 | extern void delete_write_fd (int fd); | 213 | extern void delete_write_fd (int fd); |
| 214 | |||
| 215 | extern void update_processes_for_thread_death (Lisp_Object); | ||
diff --git a/src/thread.c b/src/thread.c index 40c8be9f4d5..be98b4aae1d 100644 --- a/src/thread.c +++ b/src/thread.c | |||
| @@ -22,6 +22,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 22 | #include "lisp.h" | 22 | #include "lisp.h" |
| 23 | #include "character.h" | 23 | #include "character.h" |
| 24 | #include "buffer.h" | 24 | #include "buffer.h" |
| 25 | #include "process.h" | ||
| 25 | 26 | ||
| 26 | /* FIXME */ | 27 | /* FIXME */ |
| 27 | extern void unbind_for_thread_switch (void); | 28 | extern void unbind_for_thread_switch (void); |
| @@ -176,6 +177,50 @@ acquire_global_lock (struct thread_state *self) | |||
| 176 | 177 | ||
| 177 | 178 | ||
| 178 | 179 | ||
| 180 | struct select_args | ||
| 181 | { | ||
| 182 | select_func *func; | ||
| 183 | int max_fds; | ||
| 184 | SELECT_TYPE *rfds; | ||
| 185 | SELECT_TYPE *wfds; | ||
| 186 | SELECT_TYPE *efds; | ||
| 187 | EMACS_TIME *timeout; | ||
| 188 | sigset_t *sigmask; | ||
| 189 | int result; | ||
| 190 | }; | ||
| 191 | |||
| 192 | static void | ||
| 193 | really_call_select (void *arg) | ||
| 194 | { | ||
| 195 | struct select_args *sa = arg; | ||
| 196 | struct thread_state *self = current_thread; | ||
| 197 | |||
| 198 | release_global_lock (); | ||
| 199 | sa->result = (sa->func) (sa->max_fds, sa->rfds, sa->wfds, sa->efds, | ||
| 200 | sa->timeout, sa->sigmask); | ||
| 201 | acquire_global_lock (self); | ||
| 202 | } | ||
| 203 | |||
| 204 | int | ||
| 205 | thread_select (select_func *func, int max_fds, SELECT_TYPE *rfds, | ||
| 206 | SELECT_TYPE *wfds, SELECT_TYPE *efds, EMACS_TIME *timeout, | ||
| 207 | sigset_t *sigmask) | ||
| 208 | { | ||
| 209 | struct select_args sa; | ||
| 210 | |||
| 211 | sa.func = func; | ||
| 212 | sa.max_fds = max_fds; | ||
| 213 | sa.rfds = rfds; | ||
| 214 | sa.wfds = wfds; | ||
| 215 | sa.efds = efds; | ||
| 216 | sa.timeout = timeout; | ||
| 217 | sa.sigmask = sigmask; | ||
| 218 | flush_stack_call_func (really_call_select, &sa); | ||
| 219 | return sa.result; | ||
| 220 | } | ||
| 221 | |||
| 222 | |||
| 223 | |||
| 179 | static void | 224 | static void |
| 180 | mark_one_thread (struct thread_state *thread) | 225 | mark_one_thread (struct thread_state *thread) |
| 181 | { | 226 | { |
| @@ -315,6 +360,8 @@ run_thread (void *state) | |||
| 315 | 360 | ||
| 316 | unbind_for_thread_switch (); | 361 | unbind_for_thread_switch (); |
| 317 | 362 | ||
| 363 | update_processes_for_thread_death (Fcurrent_thread ()); | ||
| 364 | |||
| 318 | /* Unlink this thread from the list of all threads. */ | 365 | /* Unlink this thread from the list of all threads. */ |
| 319 | for (iter = &all_threads; *iter != self; iter = &(*iter)->next_thread) | 366 | for (iter = &all_threads; *iter != self; iter = &(*iter)->next_thread) |
| 320 | ; | 367 | ; |
diff --git a/src/thread.h b/src/thread.h index d21887a0928..9db3c795653 100644 --- a/src/thread.h +++ b/src/thread.h | |||
| @@ -21,6 +21,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 21 | 21 | ||
| 22 | #include "regex.h" | 22 | #include "regex.h" |
| 23 | 23 | ||
| 24 | #include "sysselect.h" /* FIXME */ | ||
| 25 | #include "systime.h" /* FIXME */ | ||
| 26 | |||
| 24 | struct thread_state | 27 | struct thread_state |
| 25 | { | 28 | { |
| 26 | struct vectorlike_header header; | 29 | struct vectorlike_header header; |
| @@ -156,6 +159,18 @@ struct thread_state | |||
| 156 | /*re_char*/ unsigned char *m_whitespace_regexp; | 159 | /*re_char*/ unsigned char *m_whitespace_regexp; |
| 157 | #define whitespace_regexp (current_thread->m_whitespace_regexp) | 160 | #define whitespace_regexp (current_thread->m_whitespace_regexp) |
| 158 | 161 | ||
| 162 | /* This variable is different from waiting_for_input in keyboard.c. | ||
| 163 | It is used to communicate to a lisp process-filter/sentinel (via the | ||
| 164 | function Fwaiting_for_user_input_p) whether Emacs was waiting | ||
| 165 | for user-input when that process-filter was called. | ||
| 166 | waiting_for_input cannot be used as that is by definition 0 when | ||
| 167 | lisp code is being evalled. | ||
| 168 | This is also used in record_asynch_buffer_change. | ||
| 169 | For that purpose, this must be 0 | ||
| 170 | when not inside wait_reading_process_output. */ | ||
| 171 | int m_waiting_for_user_input_p; | ||
| 172 | #define waiting_for_user_input_p (current_thread->m_waiting_for_user_input_p) | ||
| 173 | |||
| 159 | /* The OS identifier for this thread. */ | 174 | /* The OS identifier for this thread. */ |
| 160 | sys_thread_t thread_id; | 175 | sys_thread_t thread_id; |
| 161 | 176 | ||
| @@ -194,4 +209,11 @@ extern void init_threads_once (void); | |||
| 194 | extern void init_threads (void); | 209 | extern void init_threads (void); |
| 195 | extern void syms_of_threads (void); | 210 | extern void syms_of_threads (void); |
| 196 | 211 | ||
| 212 | typedef int select_func (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, | ||
| 213 | EMACS_TIME *, sigset_t *); | ||
| 214 | |||
| 215 | int thread_select (select_func *func, int max_fds, SELECT_TYPE *rfds, | ||
| 216 | SELECT_TYPE *wfds, SELECT_TYPE *efds, EMACS_TIME *timeout, | ||
| 217 | sigset_t *sigmask); | ||
| 218 | |||
| 197 | #endif /* THREAD_H */ | 219 | #endif /* THREAD_H */ |