[PATCH] client: Add acquire-fd API to avoid requiring a polling main thread
Kristian Høgsberg
hoegsberg at gmail.com
Thu Mar 28 09:16:29 PDT 2013
On Mon, Mar 25, 2013 at 09:42:11PM +0100, Uli Schlachter wrote:
> On 25.03.2013 21:33, Thiago Macieira wrote:
> > On segunda-feira, 25 de março de 2013 19.49.32, Uli Schlachter wrote:
> >> So wl_display_acquire_fd() would do:
> >>
> >> if (old_state == VOLUNTEER_READER) {
> >> write(display->reader_pipe[1], &c, 1);
> >> pthread_cond_wait(&display->pipe_cond, &display->mutex);
> >> read(display->reader_pipe[0], &c, 1);
> >> }
> >
> > There might be a priority inversion / resource starvation problem here.
> >
> > When the other thread returns to its caller, that caller may call the dispatch
> > function again and cause it to poll(2) again, before the pipe is emptied.
> > Since the pipe is still readable, poll(2) will return immediately and it
> > returns to the caller. Nothing changed since the last time, so the caller may
> > again cause it to dispatch.
> >
> > That other thread will be always in runnable state and will be at 100% CPU
> > usage (busy-loop), waiting for this (suspended) thread to empty the pipe. The
> > OS may take some time to wake it up from cond_wait. Meanwhile, we're burning
> > CPU and consuming battery.
> >
> > Unless there's something before the call to poll(2) that will prevent it from
> > happening in the first place. I have to confess I have not yet understood this
> > problem to confirm or deny that.
>
> Well, the rest of read_events() is still executed:
>
> > + ret = poll(pfd, 2, -1);
> > + if (pfd[1].revents & POLLIN)
> > + read(display->reader_pipe[0], &c, 1);
> > +
> > + pthread_mutex_lock(&display->mutex);
> > +
> > + pthread_cond_signal(&display->pipe_cond);
> [...]
> > }
> >
> > + if (pthread_equal(display->reader, pthread_self())) {
> [...]
> > + } else {
> > + /* Some other thread signed up to read from the fd, so
> > + * just wait for the reader to do the work. */
> > + pthread_cond_wait(&display->reader_cond, &display->mutex);
> > + }
> > +
> > + return 0;
> > +}
>
> So since the LOCKED_READER already set ->reader to itself, the VOLUNTEER_READER
> will go into the else branch and sit in pthread_cond_wait() until the
> LOCKED_READER is done doings its thing. There shouldn't be a busy loop here, right?
Yeah, I think this logic is fine.
Kristian
More information about the wayland-devel
mailing list