static Lisp_Object get_process (register Lisp_Object name);
static void exec_sentinel (Lisp_Object proc, Lisp_Object reason);
-/* Mask of bits indicating the descriptors that we wait for input on. */
-
-static SELECT_TYPE input_wait_mask;
-
-/* Mask that excludes keyboard input descriptor(s). */
-
-static SELECT_TYPE non_keyboard_wait_mask;
-
-/* Mask that excludes process input descriptor(s). */
-
-static SELECT_TYPE non_process_wait_mask;
-
-/* Mask for selecting for write. */
-
-static SELECT_TYPE write_mask;
-
#ifdef NON_BLOCKING_CONNECT
-/* Mask of bits indicating the descriptors that we wait for connect to
- complete on. Once they complete, they are removed from this mask
- and added to the input_wait_mask and non_keyboard_wait_mask. */
-
-static SELECT_TYPE connect_wait_mask;
-
/* Number of bits set in connect_wait_mask. */
static int num_pending_connects;
#endif /* NON_BLOCKING_CONNECT */
\f
+enum fd_bits
+{
+ /* Read from file descriptor. */
+ FOR_READ = 1,
+ /* Write to file descriptor. */
+ FOR_WRITE = 2,
+ /* This descriptor refers to a keyboard. Only valid if FOR_READ is
+ set. */
+ KEYBOARD_FD = 4,
+ /* This descriptor refers to a process. */
+ PROCESS_FD = 8,
+ /* A non-blocking connect. Only valid if FOR_WRITE is set. */
+ NON_BLOCKING_CONNECT_FD = 16
+};
+
static struct fd_callback_data
{
fd_callback func;
void *data;
-#define FOR_READ 1
-#define FOR_WRITE 2
- int condition; /* mask of the defines above. */
+ /* Flags from enum fd_bits. */
+ int flags;
} fd_callback_info[MAXDESC];
fd_callback_info[fd].func = func;
fd_callback_info[fd].data = data;
- fd_callback_info[fd].condition |= FOR_READ;
+}
+
+void
+add_non_keyboard_read_fd (int fd)
+{
+ eassert (fd >= 0 && fd < MAXDESC);
+ eassert (fd_callback_info[fd].func == NULL);
+ fd_callback_info[fd].flags |= FOR_READ;
+ if (fd > max_input_desc)
+ max_input_desc = fd;
+}
+
+void
+add_process_read_fd (int fd)
+{
+ add_non_keyboard_read_fd (fd);
+ fd_callback_info[fd].flags |= PROCESS_FD;
}
/* Stop monitoring file descriptor FD for when read is possible. */
eassert (fd < MAXDESC);
delete_keyboard_wait_descriptor (fd);
- fd_callback_info[fd].condition &= ~FOR_READ;
- if (fd_callback_info[fd].condition == 0)
+ if (fd_callback_info[fd].flags == 0)
{
fd_callback_info[fd].func = 0;
fd_callback_info[fd].data = 0;
add_write_fd (int fd, fd_callback func, void *data)
{
eassert (fd < MAXDESC);
- FD_SET (fd, &write_mask);
if (fd > max_input_desc)
max_input_desc = fd;
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;
+}
+
+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_input_desc)
+ max_input_desc = fd;
+ ++num_pending_connects;
}
/* Stop monitoring file descriptor FD for when write is possible. */
int lim = max_input_desc;
eassert (fd < MAXDESC);
- FD_CLR (fd, &write_mask);
- fd_callback_info[fd].condition &= ~FOR_WRITE;
- if (fd_callback_info[fd].condition == 0)
+ if ((fd_callback_info[fd].flags & NON_BLOCKING_CONNECT_FD) != 0)
+ {
+ if (--num_pending_connects < 0)
+ abort ();
+ }
+ fd_callback_info[fd].flags &= ~(FOR_WRITE | NON_BLOCKING_CONNECT_FD);
+ if (fd_callback_info[fd].flags == 0)
{
fd_callback_info[fd].func = 0;
fd_callback_info[fd].data = 0;
if (fd == max_input_desc)
- for (fd = lim; fd >= 0; fd--)
- if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask))
- {
- max_input_desc = fd;
- break;
- }
+ {
+ for (fd = max_input_desc; fd >= 0; --fd)
+ {
+ if (fd_callback_info[fd].flags != 0)
+ {
+ max_input_desc = fd;
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void
+compute_input_wait_mask (SELECT_TYPE *mask)
+{
+ int fd;
+ FD_ZERO (mask);
+ for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd)
+ {
+ if ((fd_callback_info[fd].flags & FOR_READ) != 0)
+ FD_SET (fd, mask);
}
}
+static void
+compute_non_process_wait_mask (SELECT_TYPE *mask)
+{
+ int fd;
+
+ FD_ZERO (mask);
+ for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd)
+ {
+ if ((fd_callback_info[fd].flags & FOR_READ) != 0
+ && (fd_callback_info[fd].flags & PROCESS_FD) == 0)
+ FD_SET (fd, mask);
+ }
+}
+
+static void
+compute_non_keyboard_wait_mask (SELECT_TYPE *mask)
+{
+ int fd;
+
+ FD_ZERO (mask);
+ for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd)
+ {
+ if ((fd_callback_info[fd].flags & FOR_READ) != 0
+ && (fd_callback_info[fd].flags & KEYBOARD_FD) == 0)
+ FD_SET (fd, mask);
+ }
+}
+
+static void
+compute_write_mask (SELECT_TYPE *mask)
+{
+ int fd;
+
+ FD_ZERO (mask);
+ for (fd = 0; fd < max (max_process_desc, max_input_desc); ++fd)
+ {
+ if ((fd_callback_info[fd].flags & FOR_WRITE) != 0)
+ FD_SET (fd, mask);
+ }
+}
+
+
+
\f
/* Compute the Lisp form of the process status, p->status, from
the numeric status that was returned by `wait'. */
if (p->infd >= 0)
{
if (EQ (filter, Qt) && !EQ (p->status, Qlisten))
- {
- FD_CLR (p->infd, &input_wait_mask);
- FD_CLR (p->infd, &non_keyboard_wait_mask);
- }
+ delete_read_fd (p->infd);
else if (EQ (p->filter, Qt)
/* Network or serial process not stopped: */
&& !EQ (p->command, Qt))
- {
- FD_SET (p->infd, &input_wait_mask);
- FD_SET (p->infd, &non_keyboard_wait_mask);
- }
+ delete_read_fd (p->infd);
}
PSET (p, filter, filter);
#endif /* HAVE_WORKING_VFORK */
pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
- FD_SET (inchannel, &input_wait_mask);
- FD_SET (inchannel, &non_keyboard_wait_mask);
- if (inchannel > max_process_desc)
- max_process_desc = inchannel;
+ add_non_keyboard_read_fd (inchannel);
/* Until we store the proper pid, enable sigchld_handler
to recognize an unknown pid as standing for this process.
PSET (XPROCESS (process), status, Qrun);
setup_process_coding_systems (process);
- FD_SET (inchannel, &input_wait_mask);
- FD_SET (inchannel, &non_keyboard_wait_mask);
- if (inchannel > max_process_desc)
- max_process_desc = inchannel;
+ add_non_keyboard_read_fd (inchannel);
XPROCESS (process)->pid = -2;
#ifdef HAVE_PTYS
p->pty_flag = 0;
if (!EQ (p->command, Qt))
- {
- FD_SET (fd, &input_wait_mask);
- FD_SET (fd, &non_keyboard_wait_mask);
- }
+ add_non_keyboard_read_fd (fd);
if (BUFFERP (buffer))
{
in that case, we still need to signal this like a non-blocking
connection. */
PSET (p, status, Qconnect);
- if (!FD_ISSET (inch, &connect_wait_mask))
- {
- FD_SET (inch, &connect_wait_mask);
- FD_SET (inch, &write_mask);
- num_pending_connects++;
- }
+ if ((fd_callback_info[inch].flags & NON_BLOCKING_CONNECT_FD) == 0)
+ add_non_blocking_write_fd (inch);
}
else
#endif
still listen for incoming connects unless it is stopped. */
if ((!EQ (p->filter, Qt) && !EQ (p->command, Qt))
|| (EQ (p->status, Qlisten) && NILP (p->command)))
- {
- FD_SET (inch, &input_wait_mask);
- FD_SET (inch, &non_keyboard_wait_mask);
- }
+ add_non_keyboard_read_fd (inch);
if (inch > max_process_desc)
max_process_desc = inch;
}
#endif
chan_process[inchannel] = Qnil;
- FD_CLR (inchannel, &input_wait_mask);
- FD_CLR (inchannel, &non_keyboard_wait_mask);
+ delete_read_fd (inchannel);
#ifdef NON_BLOCKING_CONNECT
- if (FD_ISSET (inchannel, &connect_wait_mask))
- {
- FD_CLR (inchannel, &connect_wait_mask);
- FD_CLR (inchannel, &write_mask);
- if (--num_pending_connects < 0)
- abort ();
- }
+ if ((fd_callback_info[inchannel].flags & NON_BLOCKING_CONNECT_FD) != 0)
+ delete_write_fd (inchannel);
#endif
if (inchannel == max_process_desc)
{
/* Client processes for accepted connections are not stopped initially. */
if (!EQ (p->filter, Qt))
- {
- FD_SET (s, &input_wait_mask);
- FD_SET (s, &non_keyboard_wait_mask);
- }
-
- if (s > max_process_desc)
- max_process_desc = s;
+ add_non_keyboard_read_fd (s);
/* Setup coding system for new process based on server process.
This seems to be the proper thing to do, as the coding system
if (kbd_on_hold_p ())
FD_ZERO (&Atemp);
else
- Atemp = input_wait_mask;
- Ctemp = write_mask;
+ compute_input_wait_mask (&Atemp);
+ compute_write_mask (&Ctemp);
timeout = make_emacs_time (0, 0);
if ((pselect (max (max_process_desc, max_input_desc) + 1,
}
else if (!NILP (wait_for_cell))
{
- Available = non_process_wait_mask;
+ compute_non_process_wait_mask (&Available);
check_delay = 0;
check_write = 0;
}
else
{
if (! read_kbd)
- Available = non_keyboard_wait_mask;
+ compute_non_keyboard_wait_mask (&Available);
else
- Available = input_wait_mask;
- Writeok = write_mask;
+ compute_input_wait_mask (&Available);
+ compute_write_mask (&Writeok);
#ifdef SELECT_CANT_DO_WRITE_MASK
check_write = 0;
#else
struct fd_callback_data *d = &fd_callback_info[channel];
if (FD_ISSET (channel, &Available)
&& d->func != 0
- && (d->condition & FOR_READ) != 0)
+ && (d->flags & FOR_READ) != 0)
d->func (channel, d->data, 1);
if (FD_ISSET (channel, &Writeok)
&& d->func != 0
- && (d->condition & FOR_WRITE) != 0)
+ && (d->flags & FOR_WRITE) != 0)
d->func (channel, d->data, 0);
}
for (channel = 0; channel <= max_process_desc; channel++)
{
if (FD_ISSET (channel, &Available)
- && FD_ISSET (channel, &non_keyboard_wait_mask)
- && !FD_ISSET (channel, &non_process_wait_mask))
+ && ((fd_callback_info[channel].flags & (KEYBOARD_FD | PROCESS_FD))
+ == PROCESS_FD))
{
int nread;
/* Clear the descriptor now, so we only raise the
signal once. */
- FD_CLR (channel, &input_wait_mask);
- FD_CLR (channel, &non_keyboard_wait_mask);
+ delete_read_fd (channel);
if (p->pid == -2)
{
}
#ifdef NON_BLOCKING_CONNECT
if (FD_ISSET (channel, &Writeok)
- && FD_ISSET (channel, &connect_wait_mask))
+ && (fd_callback_info[channel].flags
+ & NON_BLOCKING_CONNECT_FD) != 0)
{
struct Lisp_Process *p;
- FD_CLR (channel, &connect_wait_mask);
- FD_CLR (channel, &write_mask);
- if (--num_pending_connects < 0)
- abort ();
+ delete_write_fd (channel);
proc = chan_process[channel];
if (NILP (proc))
from the process before calling the sentinel. */
exec_sentinel (proc, build_string ("open\n"));
if (!EQ (p->filter, Qt) && !EQ (p->command, Qt))
- {
- FD_SET (p->infd, &input_wait_mask);
- FD_SET (p->infd, &non_keyboard_wait_mask);
- }
+ delete_read_fd (p->infd);
}
}
#endif /* NON_BLOCKING_CONNECT */
p = XPROCESS (process);
if (NILP (p->command)
&& p->infd >= 0)
- {
- FD_CLR (p->infd, &input_wait_mask);
- FD_CLR (p->infd, &non_keyboard_wait_mask);
- }
+ delete_read_fd (p->infd);
PSET (p, command, Qt);
return process;
}
&& p->infd >= 0
&& (!EQ (p->filter, Qt) || EQ (p->status, Qlisten)))
{
- FD_SET (p->infd, &input_wait_mask);
- FD_SET (p->infd, &non_keyboard_wait_mask);
+ add_non_keyboard_read_fd (p->infd);
#ifdef WINDOWSNT
if (fd_info[ p->infd ].flags & FILE_SERIAL)
PurgeComm (fd_info[ p->infd ].hnd, PURGE_RXABORT | PURGE_RXCLEAR);
/* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */
if (clear_desc_flag)
- {
- FD_CLR (p->infd, &input_wait_mask);
- FD_CLR (p->infd, &non_keyboard_wait_mask);
- }
+ delete_read_fd (p->infd);
/* Tell wait_reading_process_output that it needs to wake up and
look around. */
int fd;
for (fd = 0; fd <= max_input_desc; fd++)
- if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask)
- && !FD_ISSET (fd, &non_keyboard_wait_mask))
+ if (FD_ISSET (fd, mask)
+ && ((fd_callback_info[fd].flags & KEYBOARD_FD) != 0))
return 1;
return 0;
add_keyboard_wait_descriptor (int desc)
{
#ifdef subprocesses /* actually means "not MSDOS" */
- FD_SET (desc, &input_wait_mask);
- FD_SET (desc, &non_process_wait_mask);
+ eassert (desc >= 0 && desc < MAXDESC);
+ fd_callback_info[desc].flags |= FOR_READ | KEYBOARD_FD;
if (desc > max_input_desc)
max_input_desc = desc;
#endif
int fd;
int lim = max_input_desc;
- FD_CLR (desc, &input_wait_mask);
- FD_CLR (desc, &non_process_wait_mask);
+ fd_callback_info[desc].flags &= ~(FOR_READ | KEYBOARD_FD | PROCESS_FD);
if (desc == max_input_desc)
- for (fd = 0; fd < lim; fd++)
- if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask))
- max_input_desc = fd;
+ {
+ for (fd = max_input_desc; fd >= 0; --fd)
+ {
+ if (fd_callback_info[desc].flags != 0)
+ {
+ max_input_desc = fd;
+ break;
+ }
+ }
+ }
#endif
}
signal (SIGCHLD, sigchld_handler);
#endif
- FD_ZERO (&input_wait_mask);
- FD_ZERO (&non_keyboard_wait_mask);
- FD_ZERO (&non_process_wait_mask);
- FD_ZERO (&write_mask);
max_process_desc = 0;
memset (fd_callback_info, 0, sizeof (fd_callback_info));
#ifdef NON_BLOCKING_CONNECT
- FD_ZERO (&connect_wait_mask);
num_pending_connects = 0;
#endif