[PATCH] client: Add acquire-fd API to avoid requiring a polling main thread
Uli Schlachter
psychon at znc.in
Sat Apr 13 00:33:58 PDT 2013
Hi,
On 12.04.2013 22:27, Kristian Høgsberg wrote:
> 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.
Ah, ok. I was thinking that the volunteer reader would do this when it exits,
but it works here, too. But then this should be a broadcast instead of a signal,
too. (Just as below)
>>> + 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.
Thanks for standing my review. :-)
Uli
--
Sent from my Game Boy.
More information about the wayland-devel
mailing list