- int i;
- int rc;
-#ifdef __KERNEL__
- cfs_waitlink_t wl;
- cfs_time_t now;
-#else
- struct timeval then;
- struct timeval now;
-# ifdef HAVE_LIBPTHREAD
- struct timespec ts;
-# endif
- lnet_ni_t *eqwaitni = the_lnet.ln_eqwaitni;
-#endif
- ENTRY;
-
- LASSERT (the_lnet.ln_init);
- LASSERT (the_lnet.ln_refcount > 0);
-
- if (neq < 1)
- RETURN(-ENOENT);
-
- LNET_LOCK();
-
- for (;;) {
-#ifndef __KERNEL__
- LNET_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_LOCK();
-#endif
- for (i = 0; i < neq; i++) {
- lnet_eq_t *eq = lnet_handle2eq(&eventqs[i]);
-
- if (eq == NULL) {
- LNET_UNLOCK();
- RETURN(-ENOENT);
- }
-
- rc = lib_get_event (eq, event);
- if (rc != 0) {
- LNET_UNLOCK();
- *which = i;
- RETURN(rc);
- }
- }
-
-#ifdef __KERNEL__
- if (timeout_ms == 0) {
- LNET_UNLOCK();
- RETURN (0);
- }
-
- cfs_waitlink_init(&wl);
- cfs_set_current_state(CFS_TASK_INTERRUPTIBLE);
- cfs_waitq_add(&the_lnet.ln_waitq, &wl);
-
- LNET_UNLOCK();
-
- if (timeout_ms < 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(timeout_ms)/1000);
- cfs_duration_usec(cfs_time_sub(cfs_time_current(), now),
- &tv);
- timeout_ms -= (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
- if (timeout_ms < 0)
- timeout_ms = 0;
- }
-
- LNET_LOCK();
- cfs_waitq_del(&the_lnet.ln_waitq, &wl);
-#else
- if (eqwaitni != NULL) {
- /* I have a single NI that I have to call into, to get
- * events queued, or to block. */
- lnet_ni_addref_locked(eqwaitni);
- LNET_UNLOCK();
-
- if (timeout_ms <= 0) {
- (eqwaitni->ni_lnd->lnd_wait)(eqwaitni, timeout_ms);
- } else {
- gettimeofday(&then, NULL);
-
- (eqwaitni->ni_lnd->lnd_wait)(eqwaitni, timeout_ms);
-
- gettimeofday(&now, NULL);
- timeout_ms -= (now.tv_sec - then.tv_sec) * 1000 +
- (now.tv_usec - then.tv_usec) / 1000;
- if (timeout_ms < 0)
- timeout_ms = 0;
- }
-
- LNET_LOCK();
- lnet_ni_decref_locked(eqwaitni);
-
- /* don't call into eqwaitni again if timeout has
- * expired */
- if (timeout_ms == 0)
- eqwaitni = NULL;
-
- continue; /* go back and check for events */
- }
-
- if (timeout_ms == 0) {
- LNET_UNLOCK();
- RETURN (0);
- }
-
-# ifndef HAVE_LIBPTHREAD
- /* If I'm single-threaded, LNET fails at startup if it can't
- * set the_lnet.ln_eqwaitni correctly. */
- LBUG();
-# else
- if (timeout_ms < 0) {
- pthread_cond_wait(&the_lnet.ln_cond,
- &the_lnet.ln_lock);
- } else {
- gettimeofday(&then, NULL);
-
- ts.tv_sec = then.tv_sec + timeout_ms/1000;
- ts.tv_nsec = then.tv_usec * 1000 +
- (timeout_ms%1000) * 1000000;
- if (ts.tv_nsec >= 1000000000) {
- ts.tv_sec++;
- ts.tv_nsec -= 1000000000;
- }
-
- pthread_cond_timedwait(&the_lnet.ln_cond,
- &the_lnet.ln_lock, &ts);
-
- gettimeofday(&now, NULL);
- timeout_ms -= (now.tv_sec - then.tv_sec) * 1000 +
- (now.tv_usec - then.tv_usec) / 1000;
-
- if (timeout_ms < 0)
- timeout_ms = 0;
- }
-# endif
-#endif
- }
+ 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 = 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);
+ if (wait < 0) /* no new event */
+ break;
+ }
+
+ lnet_eq_wait_unlock();
+ RETURN(0);