+ eq->eq_deq_seq = new_event->sequence + 1;
+ RETURN(rc);
+}
+
+/**
+ * A nonblocking function that can be used to get the next event in an EQ.
+ * If an event handler is associated with the EQ, the handler will run before
+ * this function returns successfully. The event is removed from the queue.
+ *
+ * \param eventq A handle for the event queue.
+ * \param event On successful return (1 or -EOVERFLOW), this location will
+ * hold the next event in the EQ.
+ *
+ * \retval 0 No pending event in the EQ.
+ * \retval 1 Indicates success.
+ * \retval -ENOENT If \a eventq does not point to a valid EQ.
+ * \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 has been dropped due to limited space in the EQ.
+ */
+int
+LNetEQGet (lnet_handle_eq_t eventq, lnet_event_t *event)
+{
+ int which;
+
+ return LNetEQPoll(&eventq, 1, 0,
+ event, &which);
+}
+EXPORT_SYMBOL(LNetEQGet);
+
+/**
+ * Block the calling process until there is an event in the EQ.
+ * If an event handler is associated with the EQ, the handler will run before
+ * this function returns successfully. This function returns the next event
+ * in the EQ and removes it from the EQ.
+ *
+ * \param eventq A handle for the event queue.
+ * \param event On successful return (1 or -EOVERFLOW), this location will
+ * hold the next event in the EQ.
+ *
+ * \retval 1 Indicates success.
+ * \retval -ENOENT If \a eventq does not point to a valid EQ.
+ * \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 has been dropped due to limited space in the EQ.
+ */
+int
+LNetEQWait (lnet_handle_eq_t eventq, lnet_event_t *event)
+{
+ int which;
+
+ return LNetEQPoll(&eventq, 1, LNET_TIME_FOREVER,
+ event, &which);
+}
+EXPORT_SYMBOL(LNetEQWait);
+
+#ifdef __KERNEL__
+
+static int
+lnet_eq_wait_locked(int *timeout_ms)
+{
+ int tms = *timeout_ms;
+ int wait;
+ cfs_waitlink_t wl;
+ cfs_time_t now;
+
+ if (tms == 0)
+ return -1; /* don't want to wait and no new event */
+
+ cfs_waitlink_init(&wl);
+ cfs_set_current_state(CFS_TASK_INTERRUPTIBLE);
+ cfs_waitq_add(&the_lnet.ln_eq_waitq, &wl);
+
+ lnet_eq_wait_unlock();
+
+ if (tms < 0) {
+ cfs_waitq_wait(&wl, CFS_TASK_INTERRUPTIBLE);
+
+ } else {
+ struct timeval tv;
+
+ now = cfs_time_current();
+ cfs_waitq_timedwait(&wl, CFS_TASK_INTERRUPTIBLE,
+ cfs_time_seconds(tms) / 1000);
+ cfs_duration_usec(cfs_time_sub(cfs_time_current(), now), &tv);
+ tms -= (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
+ if (tms < 0) /* no more wait but may have new event */
+ tms = 0;
+ }
+
+ wait = tms != 0; /* might need to call here again */
+ *timeout_ms = tms;
+
+ lnet_eq_wait_lock();
+ cfs_waitq_del(&the_lnet.ln_eq_waitq, &wl);
+
+ return wait;
+}
+
+#else /* !__KERNEL__ */
+
+# ifdef HAVE_LIBPTHREAD
+static void
+lnet_eq_cond_wait(struct timespec *ts)
+{
+ if (ts == NULL) {
+ pthread_cond_wait(&the_lnet.ln_eq_cond,
+ &the_lnet.ln_eq_wait_lock);
+ } else {
+ pthread_cond_timedwait(&the_lnet.ln_eq_cond,
+ &the_lnet.ln_eq_wait_lock, ts);
+ }
+}
+# endif
+
+static int
+lnet_eq_wait_locked(int *timeout_ms)
+{
+ lnet_ni_t *eq_waitni = NULL;
+ int tms = *timeout_ms;
+ int wait;
+ struct timeval then;
+ struct timeval now;
+
+ if (the_lnet.ln_eq_waitni != NULL) {
+ /* I have a single NI that I have to call into, to get
+ * events queued, or to block. */
+ lnet_eq_wait_unlock();
+
+ lnet_net_lock(0);
+ eq_waitni = the_lnet.ln_eq_waitni;
+ if (unlikely(eq_waitni == NULL)) {
+ lnet_net_unlock(0);
+
+ lnet_eq_wait_lock();
+ return -1;
+ }
+
+ lnet_ni_addref_locked(eq_waitni, 0);
+ lnet_net_unlock(0);
+
+ if (tms <= 0) { /* even for tms == 0 */
+ (eq_waitni->ni_lnd->lnd_wait)(eq_waitni, tms);
+
+ } else {
+ gettimeofday(&then, NULL);
+
+ (eq_waitni->ni_lnd->lnd_wait)(eq_waitni, tms);
+
+ gettimeofday(&now, NULL);
+ tms -= (now.tv_sec - then.tv_sec) * 1000 +
+ (now.tv_usec - then.tv_usec) / 1000;
+ if (tms < 0)
+ tms = 0;
+ }
+
+ lnet_ni_decref(eq_waitni);
+ lnet_eq_wait_lock();
+ } else { /* w/o eq_waitni */
+# ifndef HAVE_LIBPTHREAD
+ /* If I'm single-threaded, LNET fails at startup if it can't
+ * set the_lnet.ln_eqwaitni correctly. */
+ LBUG();
+# else /* HAVE_LIBPTHREAD */
+ struct timespec ts;
+
+ if (tms == 0) /* don't want to wait and new event */
+ return -1;
+
+ if (tms < 0) {
+ lnet_eq_cond_wait(NULL);
+
+ } else {
+
+ gettimeofday(&then, NULL);
+
+ ts.tv_sec = then.tv_sec + tms / 1000;
+ ts.tv_nsec = then.tv_usec * 1000 +
+ (tms % 1000) * 1000000;
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000;
+ }
+
+ lnet_eq_cond_wait(&ts);
+
+ gettimeofday(&now, NULL);
+ tms -= (now.tv_sec - then.tv_sec) * 1000 +
+ (now.tv_usec - then.tv_usec) / 1000;
+ if (tms < 0)
+ tms = 0;
+ }
+# endif /* HAVE_LIBPTHREAD */
+ }
+
+ wait = tms != 0;
+ *timeout_ms = tms;
+
+ return wait;
+}
+
+#endif /* __KERNEL__ */
+
+
+/**
+ * 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 EQ handles, and size of the array.
+ * \param timeout_ms Time in milliseconds to wait for an event to occur on
+ * one of the EQs. The constant LNET_TIME_FOREVER 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(lnet_handle_eq_t *eventqs, int neq, int timeout_ms,
+ lnet_event_t *event, int *which)
+{
+ int wait = 1;
+ int rc;
+ int i;
+ ENTRY;
+
+ LASSERT (the_lnet.ln_init);
+ LASSERT (the_lnet.ln_refcount > 0);
+
+ if (neq < 1)
+ RETURN(-ENOENT);
+
+ lnet_eq_wait_lock();
+
+ for (;;) {
+#ifndef __KERNEL__
+ lnet_eq_wait_unlock();
+
+ /* Recursion breaker */
+ if (the_lnet.ln_rc_state == LNET_RC_STATE_RUNNING &&
+ !LNetHandleIsEqual(eventqs[0], the_lnet.ln_rc_eqh))
+ lnet_router_checker();
+
+ lnet_eq_wait_lock();
+#endif
+ for (i = 0; i < neq; i++) {
+ lnet_eq_t *eq = lnet_handle2eq(&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_ms);
+ if (wait < 0) /* no new event */
+ break;
+ }