in vboxguest/vboxguest_core.c [1187:1232]
static int vbg_ioctl_wait_for_events(struct vbg_dev *gdev,
struct vbg_session *session,
struct vbg_ioctl_wait_for_events *wait)
{
u32 timeout_ms = wait->u.in.timeout_ms;
u32 event_mask = wait->u.in.events;
unsigned long flags;
long timeout;
int ret = 0;
if (vbg_ioctl_chk(&wait->hdr, sizeof(wait->u.in), sizeof(wait->u.out)))
return -EINVAL;
if (timeout_ms == U32_MAX)
timeout = MAX_SCHEDULE_TIMEOUT;
else
timeout = msecs_to_jiffies(timeout_ms);
wait->u.out.events = 0;
do {
timeout = wait_event_interruptible_timeout(
gdev->event_wq,
vbg_wait_event_cond(gdev, session, event_mask),
timeout);
spin_lock_irqsave(&gdev->event_spinlock, flags);
if (timeout < 0 || session->cancel_waiters) {
ret = -EINTR;
} else if (timeout == 0) {
ret = -ETIMEDOUT;
} else {
wait->u.out.events =
vbg_consume_events_locked(gdev, session, event_mask);
}
spin_unlock_irqrestore(&gdev->event_spinlock, flags);
/*
* Someone else may have consumed the event(s) first, in
* which case we go back to waiting.
*/
} while (ret == 0 && wait->u.out.events == 0);
return ret;
}