summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamey Sharp <jamey@minilop.net>2010-04-17 17:59:11 -0700
committerJamey Sharp <jamey@minilop.net>2010-04-17 18:20:41 -0700
commitb0525e242368fffbc77ebb45293f34e80847e65a (patch)
tree3665cf5324cb6a0b88a99d79da850ce4aa7220d3
parenteff3851ba80c42b5b3ba240f7e9049d7b0fac6f0 (diff)
Always wake up readers after writing.
Since writers must make sure they read as well, threads may have gone to sleep waiting for the opportunity to read. The writer must wake up one of those readers or the application can hang. Signed-off-by: Jamey Sharp <jamey@minilop.net> Reviewed-by: Josh Triplett <josh@freedesktop.org>
-rw-r--r--src/xcb_in.c24
-rw-r--r--src/xcb_out.c1
-rw-r--r--src/xcbint.h2
3 files changed, 15 insertions, 12 deletions
diff --git a/src/xcb_in.c b/src/xcb_in.c
index a2f7312..6dd358c 100644
--- a/src/xcb_in.c
+++ b/src/xcb_in.c
@@ -69,16 +69,6 @@ typedef struct reader_list {
struct reader_list *next;
} reader_list;
-static void wake_up_next_reader(xcb_connection_t *c)
-{
- int pthreadret;
- if(c->in.readers)
- pthreadret = pthread_cond_signal(c->in.readers->data);
- else
- pthreadret = pthread_cond_signal(&c->in.event_cond);
- assert(pthreadret == 0);
-}
-
static int read_packet(xcb_connection_t *c)
{
xcb_generic_reply_t genrep;
@@ -402,7 +392,7 @@ void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_
pthread_cond_destroy(&cond);
}
- wake_up_next_reader(c);
+ _xcb_in_wake_up_next_reader(c);
pthread_mutex_unlock(&c->iolock);
return ret;
}
@@ -545,7 +535,7 @@ xcb_generic_event_t *xcb_wait_for_event(xcb_connection_t *c)
if(!_xcb_conn_wait(c, &c->in.event_cond, 0, 0))
break;
- wake_up_next_reader(c);
+ _xcb_in_wake_up_next_reader(c);
pthread_mutex_unlock(&c->iolock);
return ret;
}
@@ -629,6 +619,16 @@ void _xcb_in_destroy(_xcb_in *in)
}
}
+void _xcb_in_wake_up_next_reader(xcb_connection_t *c)
+{
+ int pthreadret;
+ if(c->in.readers)
+ pthreadret = pthread_cond_signal(c->in.readers->data);
+ else
+ pthreadret = pthread_cond_signal(&c->in.event_cond);
+ assert(pthreadret == 0);
+}
+
int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds workaround, int flags)
{
pending_reply *pend = malloc(sizeof(pending_reply));
diff --git a/src/xcb_out.c b/src/xcb_out.c
index afc12c1..fbce7a0 100644
--- a/src/xcb_out.c
+++ b/src/xcb_out.c
@@ -338,6 +338,7 @@ int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count);
c->out.request_written = c->out.request;
pthread_cond_broadcast(&c->out.cond);
+ _xcb_in_wake_up_next_reader(c);
return ret;
}
diff --git a/src/xcbint.h b/src/xcbint.h
index 9d44238..f07add8 100644
--- a/src/xcbint.h
+++ b/src/xcbint.h
@@ -137,6 +137,8 @@ typedef struct _xcb_in {
int _xcb_in_init(_xcb_in *in);
void _xcb_in_destroy(_xcb_in *in);
+void _xcb_in_wake_up_next_reader(xcb_connection_t *c);
+
int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds workaround, int flags);
void _xcb_in_replies_done(xcb_connection_t *c);