-
-static int
-lnet_eq_dequeue_event(struct lnet_eq *eq, struct lnet_event *ev)
-{
- int new_index = eq->eq_deq_seq & (eq->eq_size - 1);
- struct lnet_event *new_event = &eq->eq_events[new_index];
- int rc;
- ENTRY;
-
- /* must called with lnet_eq_wait_lock hold */
- if (LNET_SEQ_GT(eq->eq_deq_seq, new_event->sequence))
- RETURN(0);
-
- /* We've got a new event... */
- *ev = *new_event;
-
- CDEBUG(D_INFO, "event: %p, sequence: %lu, eq->size: %u\n",
- new_event, eq->eq_deq_seq, eq->eq_size);
-
- /* ...but did it overwrite an event we've not seen yet? */
- if (eq->eq_deq_seq == new_event->sequence) {
- rc = 1;
- } else {
- /* don't complain with CERROR: some EQs are sized small
- * anyway; if it's important, the caller should complain */
- CDEBUG(D_NET, "Event Queue Overflow: eq seq %lu ev seq %lu\n",
- eq->eq_deq_seq, new_event->sequence);
- rc = -EOVERFLOW;
- }
-
- eq->eq_deq_seq = new_event->sequence + 1;
- RETURN(rc);
-}
-
-static int
-lnet_eq_wait_locked(signed long *timeout)
-__must_hold(&the_lnet.ln_eq_wait_lock)
-{
- signed long tms = *timeout;
- wait_queue_entry_t wl;
- int wait;
-
- if (tms == 0)
- return -ENXIO; /* don't want to wait and no new event */
-
- init_waitqueue_entry(&wl, current);
- add_wait_queue(&the_lnet.ln_eq_waitq, &wl);
-
- lnet_eq_wait_unlock();
-
- tms = schedule_timeout_interruptible(tms);
- wait = tms != 0; /* might need to call here again */
- *timeout = tms;
-
- lnet_eq_wait_lock();
- remove_wait_queue(&the_lnet.ln_eq_waitq, &wl);
-
- return wait;
-}
-
-/**
- * Block the calling process until there's an event from a set of EQs or
- * timeout happens.
- *
- * If an event handler is associated with the EQ, the handler will run before
- * this function returns successfully, in which case the corresponding event
- * is consumed.
- *
- * LNetEQPoll() provides a timeout to allow applications to poll, block for a
- * fixed period, or block indefinitely.
- *
- * \param eventqs,neq An array of lnet_eq, and size of the array.
- * \param timeout Time in jiffies to wait for an event to occur on
- * one of the EQs. The constant MAX_SCHEDULE_TIMEOUT can be used to indicate an
- * infinite timeout.
- * \param event,which On successful return (1 or -EOVERFLOW), \a event will
- * hold the next event in the EQs, and \a which will contain the index of the
- * EQ from which the event was taken.
- *
- * \retval 0 No pending event in the EQs after timeout.
- * \retval 1 Indicates success.
- * \retval -EOVERFLOW Indicates success (i.e., an event is returned) and that
- * at least one event between this event and the last event obtained from the
- * EQ indicated by \a which has been dropped due to limited space in the EQ.
- * \retval -ENOENT If there's an invalid handle in \a eventqs.
- */
-int
-LNetEQPoll(struct lnet_eq **eventqs, int neq, signed long timeout,
- struct lnet_event *event, int *which)
-{
- int wait = 1;
- int rc;
- int i;
- ENTRY;
-
- LASSERT(the_lnet.ln_refcount > 0);
-
- if (neq < 1)
- RETURN(-ENOENT);
-
- lnet_eq_wait_lock();
-
- for (;;) {
- for (i = 0; i < neq; i++) {
- struct lnet_eq *eq = eventqs[i];
-
- if (eq == NULL) {
- lnet_eq_wait_unlock();
- RETURN(-ENOENT);
- }
-
- rc = lnet_eq_dequeue_event(eq, event);
- if (rc != 0) {
- lnet_eq_wait_unlock();
- *which = i;
- RETURN(rc);
- }
- }
-
- if (wait == 0)
- break;
-
- /*
- * return value of lnet_eq_wait_locked:
- * -1 : did nothing and it's sure no new event
- * 1 : sleep inside and wait until new event
- * 0 : don't want to wait anymore, but might have new event
- * so need to call dequeue again
- */
- wait = lnet_eq_wait_locked(&timeout);
- if (wait < 0) /* no new event */
- break;
- }
-
- lnet_eq_wait_unlock();
- RETURN(0);
-}