summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--console-client/kbd-repeat.c3
-rw-r--r--console-client/pc-mouse.c3
-rw-r--r--libpipe/pipe.c89
-rw-r--r--libpipe/pipe.h9
-rw-r--r--pfinet/tunnel.c2
-rw-r--r--term/devio.c1
-rw-r--r--term/hurdio.c1
-rw-r--r--term/main.c2
-rw-r--r--term/ptyio.c4
-rw-r--r--term/term.h25
-rw-r--r--trans/streamio.c15
11 files changed, 120 insertions, 34 deletions
diff --git a/console-client/kbd-repeat.c b/console-client/kbd-repeat.c
index 4bf9268e..b9000b22 100644
--- a/console-client/kbd-repeat.c
+++ b/console-client/kbd-repeat.c
@@ -81,6 +81,7 @@ kbd_repeat_key (kd_event *key)
memcpy (ev, key, sizeof (kd_event));
condition_broadcast (&kbdbuf.readcond);
+ condition_broadcast (&select_alert);
mutex_unlock (&global_lock);
}
@@ -231,9 +232,7 @@ kbd_setrepeater (const char *nodename, consnode_t *cn)
condition_init (&kbdbuf.readcond);
condition_init (&kbdbuf.writecond);
-
condition_init (&select_alert);
- condition_implies (&kbdbuf.readcond, &select_alert);
console_register_consnode (*cn);
diff --git a/console-client/pc-mouse.c b/console-client/pc-mouse.c
index cf8987bf..8a9009fb 100644
--- a/console-client/pc-mouse.c
+++ b/console-client/pc-mouse.c
@@ -105,6 +105,7 @@ repeat_event (kd_event *evt)
memcpy (ev, evt, sizeof (kd_event));
condition_broadcast (&mousebuf.readcond);
+ condition_broadcast (&select_alert);
mutex_unlock (&global_lock);
}
@@ -499,9 +500,7 @@ setrepeater (const char *nodename)
condition_init (&mousebuf.readcond);
condition_init (&mousebuf.writecond);
-
condition_init (&select_alert);
- condition_implies (&mousebuf.readcond, &select_alert);
console_register_consnode (cnode);
diff --git a/libpipe/pipe.c b/libpipe/pipe.c
index 914816bc..85aac0e6 100644
--- a/libpipe/pipe.c
+++ b/libpipe/pipe.c
@@ -64,6 +64,7 @@ pipe_create (struct pipe_class *class, struct pipe **pipe)
condition_init (&new->pending_read_selects);
condition_init (&new->pending_writes);
condition_init (&new->pending_write_selects);
+ new->pending_selects = NULL;
mutex_init (&new->lock);
pq_create (&new->queue);
@@ -83,6 +84,63 @@ pipe_free (struct pipe *pipe)
free (pipe);
}
+static void
+pipe_add_select_cond (struct pipe *pipe, struct pipe_select_cond *cond)
+{
+ struct pipe_select_cond *first, *last;
+
+ first = pipe->pending_selects;
+
+ if (first == NULL)
+ {
+ cond->next = cond;
+ cond->prev = cond;
+ pipe->pending_selects = cond;
+ return;
+ }
+
+ last = first->prev;
+ cond->next = first;
+ cond->prev = last;
+ first->prev = cond;
+ last->next = cond;
+}
+
+static void
+pipe_remove_select_cond (struct pipe *pipe, struct pipe_select_cond *cond)
+{
+ cond->prev->next = cond->next;
+ cond->next->prev = cond->prev;
+
+ if (pipe->pending_selects == cond)
+ {
+ if (cond->next == cond)
+ pipe->pending_selects = NULL;
+ else
+ pipe->pending_selects = cond->next;
+ }
+}
+
+static void
+pipe_select_cond_broadcast (struct pipe *pipe)
+{
+ struct pipe_select_cond *cond, *last;
+
+ cond = pipe->pending_selects;
+
+ if (cond == NULL)
+ return;
+
+ last = cond->prev;
+
+ do
+ {
+ condition_broadcast (&cond->cond);
+ cond = cond->next;
+ }
+ while (cond != last);
+}
+
/* Take any actions necessary when PIPE acquires its first writer. */
void _pipe_first_writer (struct pipe *pipe)
{
@@ -113,6 +171,7 @@ void _pipe_no_readers (struct pipe *pipe)
{
condition_broadcast (&pipe->pending_writes);
condition_broadcast (&pipe->pending_write_selects);
+ pipe_select_cond_broadcast (pipe);
}
}
mutex_unlock (&pipe->lock);
@@ -135,6 +194,7 @@ void _pipe_no_writers (struct pipe *pipe)
{
condition_broadcast (&pipe->pending_reads);
condition_broadcast (&pipe->pending_read_selects);
+ pipe_select_cond_broadcast (pipe);
}
}
mutex_unlock (&pipe->lock);
@@ -171,22 +231,22 @@ pipe_pair_select (struct pipe *rpipe, struct pipe *wpipe,
/* ugh */
{
int rpipe_blocked, wpipe_blocked;
- struct condition pending_read_write_select;
+ struct pipe_select_cond pending_select;
size_t wlimit = wpipe->write_limit;
struct mutex *lock =
(wpipe == rpipe ? &rpipe->lock : &pipe_multiple_lock);
- condition_init (&pending_read_write_select);
- condition_implies (&rpipe->pending_read_selects,
- &pending_read_write_select);
- condition_implies (&wpipe->pending_write_selects,
- &pending_read_write_select);
+ condition_init (&pending_select.cond);
mutex_lock (lock);
- if (rpipe != wpipe)
+ if (rpipe == wpipe)
+ pipe_add_select_cond (rpipe, &pending_select);
+ else
{
mutex_lock (&rpipe->lock);
mutex_lock (&wpipe->lock);
+ pipe_add_select_cond (rpipe, &pending_select);
+ pipe_add_select_cond (wpipe, &pending_select);
}
rpipe_blocked =
@@ -200,7 +260,7 @@ pipe_pair_select (struct pipe *rpipe, struct pipe *wpipe,
mutex_unlock (&rpipe->lock);
mutex_unlock (&wpipe->lock);
}
- if (hurd_condition_wait (&pending_read_write_select, lock))
+ if (hurd_condition_wait (&pending_select.cond, lock))
err = EINTR;
if (rpipe != wpipe)
{
@@ -223,17 +283,16 @@ pipe_pair_select (struct pipe *rpipe, struct pipe *wpipe,
*select_type &= ~SELECT_WRITE;
}
- if (rpipe != wpipe)
+ if (rpipe == wpipe)
+ pipe_remove_select_cond (rpipe, &pending_select);
+ else
{
+ pipe_remove_select_cond (rpipe, &pending_select);
+ pipe_remove_select_cond (wpipe, &pending_select);
mutex_unlock (&rpipe->lock);
mutex_unlock (&wpipe->lock);
}
mutex_unlock (lock);
-
- condition_unimplies (&rpipe->pending_read_selects,
- &pending_read_write_select);
- condition_unimplies (&wpipe->pending_write_selects,
- &pending_read_write_select);
}
return err;
@@ -306,6 +365,7 @@ pipe_send (struct pipe *pipe, int noblock, void *source,
if (pipe_is_readable (pipe, 0))
{
condition_broadcast (&pipe->pending_read_selects);
+ pipe_select_cond_broadcast (pipe);
/* We leave PIPE locked here, assuming the caller will soon unlock
it and allow others access. */
}
@@ -407,6 +467,7 @@ pipe_recv (struct pipe *pipe, int noblock, unsigned *flags, void **source,
if (pipe_readable (pipe, 1) < pipe->write_limit)
{
condition_broadcast (&pipe->pending_write_selects);
+ pipe_select_cond_broadcast (pipe);
/* We leave PIPE locked here, assuming the caller will soon unlock
it and allow others access. */
}
diff --git a/libpipe/pipe.h b/libpipe/pipe.h
index 96432990..a3590fc4 100644
--- a/libpipe/pipe.h
+++ b/libpipe/pipe.h
@@ -62,6 +62,13 @@ extern struct pipe_class *stream_pipe_class;
extern struct pipe_class *dgram_pipe_class;
extern struct pipe_class *seqpack_pipe_class;
+struct pipe_select_cond
+{
+ struct pipe_select_cond *next;
+ struct pipe_select_cond *prev;
+ struct condition cond;
+};
+
/* A unidirectional data pipe; it transfers data from READER to WRITER. */
struct pipe
{
@@ -88,6 +95,8 @@ struct pipe
struct condition pending_writes;
struct condition pending_write_selects;
+ struct pipe_select_cond *pending_selects;
+
/* The maximum number of characters that this pipe will hold without
further writes blocking. */
size_t write_limit;
diff --git a/pfinet/tunnel.c b/pfinet/tunnel.c
index ec96861a..6f9e1498 100644
--- a/pfinet/tunnel.c
+++ b/pfinet/tunnel.c
@@ -135,6 +135,7 @@ tunnel_xmit (struct sk_buff *skb, struct device *dev)
{
tdev->read_blocked = 0;
condition_broadcast (&tdev->wait);
+ condition_broadcast (&tdev->select_alert);
}
__mutex_unlock (&tdev->lock);
@@ -213,7 +214,6 @@ setup_tunnel_device (char *name, struct device **device)
__mutex_init (&tdev->lock);
condition_init (&tdev->wait);
condition_init (&tdev->select_alert);
- condition_implies (&tdev->wait, &tdev->select_alert);
/* This call adds the device to the `dev_base' chain,
initializes its `ifindex' member (which matters!),
diff --git a/term/devio.c b/term/devio.c
index 38eb996c..8aa960b9 100644
--- a/term/devio.c
+++ b/term/devio.c
@@ -323,6 +323,7 @@ device_write_reply_inband (mach_port_t replypt,
{
npending_output = 0;
condition_broadcast (outputq->wait);
+ condition_broadcast (&select_alert);
}
else
{
diff --git a/term/hurdio.c b/term/hurdio.c
index ef34740b..b1d0c944 100644
--- a/term/hurdio.c
+++ b/term/hurdio.c
@@ -286,6 +286,7 @@ hurdio_writer_loop (any_t arg)
{
npending_output = 0;
condition_broadcast (outputq->wait);
+ condition_broadcast (&select_alert);
}
else
{
diff --git a/term/main.c b/term/main.c
index 405e7cd8..e15fee53 100644
--- a/term/main.c
+++ b/term/main.c
@@ -443,8 +443,6 @@ main (int argc, char **argv)
condition_init (&carrier_alert);
condition_init (&select_alert);
- condition_implies (inputq->wait, &select_alert);
- condition_implies (outputq->wait, &select_alert);
/* Launch. */
ports_manage_port_operations_multithread (term_bucket, demuxer, 0, 0, 0);
diff --git a/term/ptyio.c b/term/ptyio.c
index 9c1509ff..b02cda3f 100644
--- a/term/ptyio.c
+++ b/term/ptyio.c
@@ -58,8 +58,7 @@ static int nptyperopens = 0;
static error_t
ptyio_init (void)
{
- condition_implies (inputq->wait, &pty_select_wakeup);
- condition_implies (&pty_read_wakeup, &pty_select_wakeup);
+ pty_select_alert = &pty_select_wakeup;
return 0;
}
@@ -132,6 +131,7 @@ wake_reader ()
{
pty_read_blocked = 0;
condition_broadcast (&pty_read_wakeup);
+ condition_broadcast (&pty_select_wakeup);
}
}
diff --git a/term/term.h b/term/term.h
index 81d0efee..2df20337 100644
--- a/term/term.h
+++ b/term/term.h
@@ -103,6 +103,9 @@ struct condition carrier_alert;
/* Wakeup for select */
struct condition select_alert;
+/* Wakeup for pty select, if not null */
+struct condition *pty_select_alert;
+
/* Bucket for all our ports. */
struct port_bucket *term_bucket;
@@ -225,6 +228,9 @@ clear_queue (struct queue *q)
q->susp = 0;
q->cs = q->ce = q->array;
condition_broadcast (q->wait);
+ condition_broadcast (&select_alert);
+ if (q == inputq && pty_select_alert != NULL)
+ condition_broadcast (pty_select_alert);
}
#endif /* Use extern inlines. */
@@ -249,7 +255,10 @@ dequeue_quote (struct queue *q)
if (beep)
{
condition_broadcast (q->wait);
- if (q == outputq)
+ condition_broadcast (&select_alert);
+ if (q == inputq && pty_select_alert != NULL)
+ condition_broadcast (pty_select_alert);
+ else if (q == outputq)
call_asyncs (O_WRITE);
}
return *q->cs++;
@@ -280,8 +289,13 @@ enqueue_internal (struct queue **qp, quoted_char c)
if (qsize (q) == 1)
{
condition_broadcast (q->wait);
+ condition_broadcast (&select_alert);
if (q == inputq)
- call_asyncs (O_READ);
+ {
+ if (pty_select_alert != NULL)
+ condition_broadcast (pty_select_alert);
+ call_asyncs (O_READ);
+ }
}
if (!q->susp && (qsize (q) > q->hiwat))
@@ -334,7 +348,12 @@ queue_erase (struct queue *q)
if (qsize (q) == 0)
beep = 1;
if (beep)
- condition_broadcast (q->wait);
+ {
+ condition_broadcast (q->wait);
+ condition_broadcast (&select_alert);
+ if (q == inputq && pty_select_alert != NULL)
+ condition_broadcast (pty_select_alert);
+ }
return answer;
}
#endif /* Use extern inlines. */
diff --git a/trans/streamio.c b/trans/streamio.c
index c563c03c..9ced28b3 100644
--- a/trans/streamio.c
+++ b/trans/streamio.c
@@ -108,6 +108,7 @@ clear_buffer (struct buffer *b)
return;
b->head = b->tail = b->buf;
condition_broadcast (b->wait);
+ condition_broadcast (&select_alert);
}
/* Read up to LEN bytes from B to DATA, returning the amount actually read. */
@@ -132,6 +133,7 @@ buffer_read (struct buffer *b, void *data, size_t len)
}
condition_broadcast (b->wait);
+ condition_broadcast (&select_alert);
return len;
}
@@ -148,6 +150,7 @@ buffer_write (struct buffer *b, void *data, size_t len)
b->tail += len;
condition_broadcast (b->wait);
+ condition_broadcast (&select_alert);
return len;
}
@@ -300,15 +303,9 @@ main (int argc, char *argv[])
condition_init (&select_alert);
if (trivfs_allow_open & O_READ)
- {
- input_buffer = create_buffer (256);
- condition_implies (input_buffer->wait, &select_alert);
- }
+ input_buffer = create_buffer (256);
if (trivfs_allow_open & O_WRITE)
- {
- output_buffer = create_buffer (256);
- condition_implies (output_buffer->wait, &select_alert);
- }
+ output_buffer = create_buffer (256);
/* Launch */
ports_manage_port_operations_multithread (streamdev_bucket, demuxer,
@@ -999,6 +996,7 @@ device_read_reply_inband (mach_port_t reply, error_t errorcode,
data += nwritten;
datalen -= nwritten;
condition_broadcast (input_buffer->wait);
+ condition_broadcast (&select_alert);
}
}
else
@@ -1102,6 +1100,7 @@ device_write_reply_inband (mach_port_t reply, error_t returncode, int amount)
{
npending_output = 0;
condition_broadcast (output_buffer->wait);
+ condition_broadcast (&select_alert);
}
else
{