process.o gnutls.o callproc.o \
region-cache.o sound.o atimer.o \
doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \
- profiler.o \
+ profiler.o decompress.o \
+ thread.o systhread.o \
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
$(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ)
obj = $(base_obj) $(NS_OBJC_OBJ)
#endif
char *ch_to_dir;
-#if GC_MARK_STACK
- stack_base = &dummy;
-#endif
+ /* Record (approximately) where the stack begins. */
+ stack_bottom = &stack_bottom_variable;
#ifdef G_SLICE_ALWAYS_MALLOC
- /* This is used by the Cygwin build. */
+ /* This is used by the Cygwin build. It's not needed starting with
+ cygwin-1.7.24, but it doesn't do any harm. */
xputenv ("G_SLICE=always-malloc");
#endif
grow_specpdl ();
}
+void
+rebind_for_thread_switch (void)
+{
+ union specbinding *bind;
+
+ for (bind = specpdl; bind != specpdl_ptr; ++bind)
+ {
+ if (bind->kind >= SPECPDL_LET)
+ {
+ Lisp_Object value = specpdl_saved_value (bind);
+
+ bind->let.saved_value = Qnil;
+ do_specbind (XSYMBOL (binding_symbol (bind)), bind, value);
+ }
+ }
+}
+
static void
- specpdl_ptr->unwind.func (specpdl_ptr->unwind.arg);
+do_one_unbind (union specbinding *this_binding, int unwinding)
+{
+ eassert (unwinding || this_binding->kind >= SPECPDL_LET);
+ switch (this_binding->kind)
+ {
+ case SPECPDL_UNWIND:
- specpdl_ptr->unwind_ptr.func (specpdl_ptr->unwind_ptr.arg);
++ this_binding->unwind.func (this_binding->unwind.arg);
+ break;
+ case SPECPDL_UNWIND_PTR:
- specpdl_ptr->unwind_int.func (specpdl_ptr->unwind_int.arg);
++ this_binding->unwind_ptr.func (this_binding->unwind_ptr.arg);
+ break;
+ case SPECPDL_UNWIND_INT:
- specpdl_ptr->unwind_void.func ();
++ this_binding->unwind_int.func (this_binding->unwind_int.arg);
+ break;
+ case SPECPDL_UNWIND_VOID:
- /* If variable has a trivial value (no forwarding), we can
- just set it. No need to check for constant symbols here,
- since that was already done by specbind. */
- if (XSYMBOL (specpdl_symbol (this_binding))->redirect
- == SYMBOL_PLAINVAL)
- SET_SYMBOL_VAL (XSYMBOL (specpdl_symbol (this_binding)),
- specpdl_old_value (this_binding));
- else
- /* NOTE: we only ever come here if make_local_foo was used for
- the first time on this var within this let. */
- Fset_default (specpdl_symbol (this_binding),
- specpdl_old_value (this_binding));
++ this_binding->unwind_void.func ();
+ break;
+ case SPECPDL_BACKTRACE:
+ break;
+ case SPECPDL_LET:
- case SPECPDL_LET_DEFAULT:
- { /* If the symbol is a list, it is really (SYMBOL WHERE
- . CURRENT-BUFFER) where WHERE is either nil, a buffer, or a
- frame. If WHERE is a buffer or frame, this indicates we
- bound a variable that had a buffer-local or frame-local
- binding. WHERE nil means that the variable had the default
- value when it was bound. CURRENT-BUFFER is the buffer that
- was current when the variable was bound. */
++ { /* If variable has a trivial value (no forwarding), we can
++ just set it. No need to check for constant symbols here,
++ since that was already done by specbind. */
++ struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (this_binding));
++ if (sym->redirect == SYMBOL_PLAINVAL)
++ {
++ SET_SYMBOL_VAL (sym, specpdl_old_value (this_binding));
++ break;
++ }
++ else
++ { /* FALLTHROUGH!!
++ NOTE: we only ever come here if make_local_foo was used for
++ the first time on this var within this let. */
++ }
++ }
++ case SPECPDL_LET_DEFAULT:
++ Fset_default (specpdl_symbol (this_binding),
++ specpdl_old_value (this_binding));
+ break;
+ case SPECPDL_LET_LOCAL:
- if (this_binding->kind == SPECPDL_LET_DEFAULT)
- Fset_default (symbol, specpdl_old_value (this_binding));
++ {
+ Lisp_Object symbol = specpdl_symbol (this_binding);
+ Lisp_Object where = specpdl_where (this_binding);
++ Lisp_Object old_value = specpdl_old_value (this_binding);
+ eassert (BUFFERP (where));
+
- else if (!NILP (Flocal_variable_p (symbol, where)))
- set_internal (symbol, specpdl_old_value (this_binding),
- where, 1);
+ /* If this was a local binding, reset the value in the appropriate
+ buffer, but only if that buffer's binding still exists. */
++ if (!NILP (Flocal_variable_p (symbol, where)))
++ set_internal (symbol, old_value, where, 1);
+ }
+ break;
+ }
+}
+
+void
do_nothing (void)
{}
extern void record_unwind_protect_void (void (*) (void));
extern void record_unwind_protect_nothing (void);
extern void clear_unwind_protect (ptrdiff_t);
+ extern void set_unwind_protect (ptrdiff_t, void (*) (Lisp_Object), Lisp_Object);
extern void set_unwind_protect_ptr (ptrdiff_t, void (*) (void *), void *);
extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object);
+extern void rebind_for_thread_switch (void);
+extern void unbind_for_thread_switch (void);
extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
extern _Noreturn void verror (const char *, va_list)
ATTRIBUTE_FORMAT_PRINTF (1, 0);
static int num_pending_connects;
#endif /* NON_BLOCKING_CONNECT */
- /* The largest descriptor currently in use for input. */
-/* The largest descriptor currently in use for a process object; -1 if none. */
-static int max_process_desc;
-
-/* The largest descriptor currently in use for input; -1 if none. */
-static int max_input_desc;
++/* The largest descriptor currently in use; -1 if none. */
+static int max_desc;
/* Indexed by descriptor, gives the process (if any) for that descriptor */
static Lisp_Object chan_process[MAXDESC];
fd_callback_info[fd].func = func;
fd_callback_info[fd].data = data;
- fd_callback_info[fd].condition |= FOR_WRITE;
+ fd_callback_info[fd].flags |= FOR_WRITE;
+}
+
+static void
+add_non_blocking_write_fd (int fd)
+{
+ eassert (fd >= 0 && fd < MAXDESC);
+ eassert (fd_callback_info[fd].func == NULL);
+
+ fd_callback_info[fd].flags |= FOR_WRITE | NON_BLOCKING_CONNECT_FD;
+ if (fd > max_desc)
+ max_desc = fd;
+ ++num_pending_connects;
+}
+
+static void
+recompute_max_desc (void)
+{
+ int fd;
+
+ for (fd = max_desc; fd >= 0; --fd)
+ {
+ if (fd_callback_info[fd].flags != 0)
+ {
+ max_desc = fd;
+ break;
+ }
+ }
}
+ /* FD is no longer an input descriptor; update max_input_desc accordingly. */
+
+ static void
+ delete_input_desc (int fd)
+ {
+ if (fd == max_input_desc)
+ {
+ do
+ fd--;
+ while (0 <= fd && ! (FD_ISSET (fd, &input_wait_mask)
+ || FD_ISSET (fd, &write_mask)));
+
+ max_input_desc = fd;
+ }
+ }
+
/* Stop monitoring file descriptor FD for when write is possible. */
void
we just reopen the device (see emacs_get_tty_pgrp) as this is
more portable (see USG_SUBTTY_WORKS above). */
- XPROCESS (process)->pty_flag = pty_flag;
- pset_status (XPROCESS (process), Qrun);
+ p->pty_flag = pty_flag;
+ pset_status (p, Qrun);
- FD_SET (inchannel, &input_wait_mask);
- FD_SET (inchannel, &non_keyboard_wait_mask);
- if (inchannel > max_process_desc)
- max_process_desc = inchannel;
+ add_process_read_fd (inchannel);
/* This may signal an error. */
setup_process_coding_systems (process);
we just reopen the device (see emacs_get_tty_pgrp) as this is
more portable (see USG_SUBTTY_WORKS above). */
- XPROCESS (process)->pty_flag = 1;
- pset_status (XPROCESS (process), Qrun);
+ p->pty_flag = 1;
+ pset_status (p, Qrun);
setup_process_coding_systems (process);
- pset_tty_name (XPROCESS (process), build_string (pty_name));
- FD_SET (pty_fd, &input_wait_mask);
- FD_SET (pty_fd, &non_keyboard_wait_mask);
- if (pty_fd > max_process_desc)
- max_process_desc = pty_fd;
++ fixme;
+
+ pset_tty_name (p, build_string (pty_name));
}
- XPROCESS (process)->pid = -2;
+ p->pid = -2;
}
\f
p = XPROCESS (proc);
fd = serial_open (port);
+ p->open_fd[SUBPROCESS_STDIN] = fd;
p->infd = fd;
p->outfd = fd;
- if (fd > max_process_desc)
- max_process_desc = fd;
+ if (fd > max_desc)
+ max_desc = fd;
chan_process[fd] = proc;
buffer = Fplist_get (contact, QCbuffer);
process_output_skip = 0;
}
#endif
-
+ nfds = thread_select (
#if defined (HAVE_NS)
- nfds = ns_select
+ ns_select
#elif defined (HAVE_GLIB)
- nfds = xg_select
+ xg_select
#else
- nfds = pselect
+ pselect
#endif
- (max (max_process_desc, max_input_desc) + 1,
- &Available,
- (check_write ? &Writeok : 0),
- NULL, &timeout, NULL);
+ , max_desc + 1,
+ &Available,
- (check_write ? &Writeok : (SELECT_TYPE *)0),
++ (check_write ? &Writeok : 0),
+ NULL, &timeout, NULL);
#ifdef HAVE_GNUTLS
/* GnuTLS buffers data internally. In lowat mode it leaves
catch_child_signal ();
}
- max_desc = 0;
- FD_ZERO (&input_wait_mask);
- FD_ZERO (&non_keyboard_wait_mask);
- FD_ZERO (&non_process_wait_mask);
- FD_ZERO (&write_mask);
- max_process_desc = max_input_desc = -1;
++ max_desc = -1;
memset (fd_callback_info, 0, sizeof (fd_callback_info));
#ifdef NON_BLOCKING_CONNECT