[PATCH] client: Add acquire-fd API to avoid requiring a polling main thread

Kristian Høgsberg hoegsberg at gmail.com
Fri Apr 12 13:27:54 PDT 2013


On Thu, Apr 11, 2013 at 09:53:58AM +0200, Uli Schlachter wrote:
> On 10.04.2013 23:55, Kristian Høgsberg wrote:
> [...]
> >+WL_EXPORT int
> >+wl_display_acquire_fd(struct wl_display *display)
> >+{
> >+	char c = 0;
> >+
> >+	pthread_mutex_lock(&display->mutex);
> >+
> >+	if (display->reader_state == LOCKED_READER &&
> >+	    !pthread_equal(display->reader, pthread_self())) {
> >+		errno = EBUSY;
> >+		pthread_mutex_unlock(&display->mutex);
> >+		return -1;
> >+	}
> >+
> >+	pthread_cond_signal(&display->pipe_cond);
> 
> I feel light I am missing something, so: Why does this call
> cond_signal() here? The only threads which might be waiting on this
> condition are waiting for the volunteer reader to exit and they will
> not be able to progress until that one unsets pipe_busy. So the
> signal() here won't do anything bad, but also none of the threads
> waking up will be able to do anything.

Oh, I guess the code is ordered a little unintuitively there... we set
reader_state = LOCKED_READER further down, which should also wake up a
thread waiting for the pipe.  When a locked reader turns up, there's
no need for a volunteer and the waiting thread can go straight to the
pthread_cond_wait(reader_cond) case instead of waiting for the pipe.

> >+	if (display->reader_state == VOLUNTEER_READER)
> >+		write(display->reader_pipe[1], &c, 1);
> >+
> >+	display->reader = pthread_self();
> >+	display->reader_state = LOCKED_READER;
> >+
> >+	pthread_mutex_unlock(&display->mutex);
> >+
> >+	return display->fd;
> >+}
> [...]
> >+		pthread_mutex_lock(&display->mutex);
> >+
> >+		display->pipe_busy = 0;
> >+		if (display->reader_state != VOLUNTEER_READER) {
> >+			read(display->reader_pipe[0], &c, 1);
> >+			pthread_cond_signal(&display->pipe_cond);
> 
> Why is this a cond_signal()? If more than one thread is waiting on
> pipe_cond, all of them should be waken up. One of them will/might
> become a volunteer reader, the others should end up waiting on
> reader_cond.
> 
> (Otherwise the volunteer reader might read something useful for one
> of the threads, but this thread is still waiting on pipe_cond).

Yup, should be broadcast there, thanks.

> >+		}
> >
> >-	ret = wl_connection_flush(display->connection);
> >-	if (ret < 0 && errno != EAGAIN) {
> >-		display_fatal_error(display, errno);
> >-		goto err_unlock;
> >+		if (ret == -1) {
> >+			display_fatal_error(display, errno);
> >+			return -1;
> >+		}
> >  	}
> [...]
> 
> The synchronization in this patch looks solid to me. I will think
> about it a little more, but I didn't yet manage to really break it.
> Yay. :-)

Thanks again for reviewing.

Kristian


More information about the wayland-devel mailing list