1) Move the wake_up() call done inside the poll callback outside the lock
void poll_cb(xxx *data)
{
int pwake = 0;
lock(data);
...
if (wait_queue_active(&data->poll_wait))
pwake++;
unlock(data)
if (pwake)
ep_poll_safe_wakeup(&data->psw, &data->poll_wait)
}
2) Use this infrastructure to perform safe poll wakeups
/*
* This is used to implement the safe poll wake up avoiding to reenter
* the poll callback from inside wake_up().
*/
struct poll_safewake {
int wakedoor; /* Init = 1, can do wake up */
atomic_t count; /* Init = 0, wake up count */
};
/* Perform a safe wake up of the poll wait list */
static void ep_poll_safe_wakeup(struct poll_safewake *psw, wait_queue_head_t *wq)
{
atomic_inc(&psw->count);
do {
if (!xchg(&psw->wakedoor, 0))
break;
wake_up(wq);
xchg(&psw->wakedoor, 1);
} while (!atomic_dec_and_test(&psw->count));
}
Does anyone foresee problem in this implementation ?
Another ( crappy ) solution might be to avoid the epoll fd to drop inside
its poll wait queue head, wait queues that has the function pointer != NULL
- Davide
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/