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/thread.c | |
| 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/thread.c')
| -rw-r--r-- | src/thread.c | 47 |
1 files changed, 47 insertions, 0 deletions
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 | ; |