1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-04 02:51:31 -08:00

Prepare process.c for threads by not having global select masks.

The next step is to make it so selects can choose fds by thread.
This commit is contained in:
Tom Tromey 2012-08-15 13:17:37 -06:00
parent 0ccc5d8998
commit aa14ccd1e2

View file

@ -267,29 +267,7 @@ static void create_pty (Lisp_Object);
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 */
@ -336,13 +314,27 @@ static int pty_max_bytes;
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];
@ -357,7 +349,23 @@ add_read_fd (int fd, fd_callback func, void *data)
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. */
@ -368,8 +376,7 @@ delete_read_fd (int fd)
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;
@ -383,13 +390,24 @@ void
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. */
@ -400,24 +418,87 @@ delete_write_fd (int fd)
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);
}
}
/* Compute the Lisp form of the process status, p->status, from
the numeric status that was returned by `wait'. */
@ -961,17 +1042,11 @@ The string argument is normally a multibyte string, except:
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);
@ -1650,10 +1725,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
#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.
@ -1968,10 +2040,7 @@ create_pty (Lisp_Object 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
@ -2616,10 +2685,7 @@ usage: (make-serial-process &rest ARGS) */)
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))
{
@ -3431,12 +3497,8 @@ usage: (make-network-process &rest ARGS) */)
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
@ -3444,10 +3506,7 @@ usage: (make-network-process &rest ARGS) */)
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;
@ -3892,16 +3951,10 @@ deactivate_process (Lisp_Object proc)
}
#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)
{
@ -4165,13 +4218,7 @@ server_accept_connection (Lisp_Object server, int channel)
/* 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
@ -4433,8 +4480,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
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,
@ -4512,17 +4559,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
}
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
@ -4790,19 +4837,19 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
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;
@ -4880,8 +4927,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
/* 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)
{
@ -4915,14 +4961,12 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
}
#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))
@ -4970,10 +5014,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
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 */
@ -6014,10 +6055,7 @@ traffic. */)
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;
}
@ -6045,8 +6083,7 @@ traffic. */)
&& 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);
@ -6419,10 +6456,7 @@ sigchld_handler (int signo)
/* 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. */
@ -6796,8 +6830,8 @@ keyboard_bit_set (fd_set *mask)
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;
@ -7042,8 +7076,8 @@ void
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
@ -7058,13 +7092,19 @@ delete_keyboard_wait_descriptor (int desc)
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
}
@ -7320,15 +7360,10 @@ init_process_emacs (void)
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