- Save one call to curlx_tvnow(), which calls gettimeofday(), in each of
  Curl_socket_ready(), Curl_poll() and Curl_select() when these are called
  with a zero timeout or a timeout value indicating a blocking call should
  be performed.

  These unnecessary calls to gettimeofday() got introduced in 7.16.2 when
  fixing 'timeout would restart when signal caught while awaiting socket
  events' on 20 March 2007.

- Move some loop breaking logic from the while clause into the loop,
  avoiding compiler warning 'assignment within conditional expression'
diff --git a/CHANGES b/CHANGES
index 94726eb..3fb9c2c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,12 @@
 
                                   Changelog
 
+Yang Tse (20 April 2007)
+- Save one call to curlx_tvnow(), which calls gettimeofday(), in each of
+  Curl_socket_ready(), Curl_poll() and Curl_select() when these are called
+  with a zero timeout or a timeout value indicating a blocking call should
+  be performed.
+
 Daniel S (18 April 2007)
 - James Housley made SFTP uploads use libssh2's non-blocking API
 
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 5dee28b..2c0c69c 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -22,6 +22,7 @@
    for a host which was supposed not to exist.
  o test suite SSL certificate works better with newer stunnel
  o internal progress meter update frequency back to once per second
+ o avoid some unnecessary calls to function gettimeofday
 
 This release includes the following known bugs:
 
diff --git a/lib/select.c b/lib/select.c
index 30aece4..9d75e77 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -76,12 +76,12 @@
 #define elapsed_ms  (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
 
 #ifdef CURL_ACKNOWLEDGE_EINTR
-#define error_not_EINTR  (error != EINTR)
+#define error_is_EINTR  (error == EINTR)
 #else
-#define error_not_EINTR  (1)
+#define error_is_EINTR  (0)
 #endif
 
-#define SMALL_POLLNFDS  0X20
+#define SMALL_POLLNFDS  0x20
 
 /*
  * Internal function used for waiting a specific amount of ms
@@ -136,9 +136,15 @@
     pending_tv.tv_usec = (pending_ms % 1000) * 1000;
     r = select(0, NULL, NULL, NULL, &pending_tv);
 #endif /* HAVE_POLL_FINE */
-  } while ((r == -1) && (error = SOCKERRNO) &&
-           (error != EINVAL) && error_not_EINTR &&
-           ((pending_ms = timeout_ms - elapsed_ms) > 0));
+    if (r != -1)
+      break;
+    error = SOCKERRNO;
+    if ((error == EINVAL) || error_is_EINTR)
+      break;
+    pending_ms = timeout_ms - elapsed_ms;
+    if (pending_ms <= 0)
+      break;
+  } while (r == -1);
 #endif /* USE_WINSOCK */
   if (r)
     r = -1;
@@ -188,8 +194,15 @@
     return r;
   }
 
-  pending_ms = timeout_ms;
-  initial_tv = curlx_tvnow();
+  /* Avoid initial timestamp, avoid gettimeofday() call, when elapsed
+     time in this function does not need to be measured. This happens
+     when function is called with a zero timeout or a negative timeout
+     value indicating a blocking call should be performed. */
+
+  if (timeout_ms > 0) {
+    pending_ms = timeout_ms;
+    initial_tv = curlx_tvnow();
+  }
 
 #ifdef HAVE_POLL_FINE
 
@@ -210,10 +223,20 @@
   do {
     if (timeout_ms < 0)
       pending_ms = -1;
+    else if (!timeout_ms)
+      pending_ms = 0;
     r = poll(pfd, num, pending_ms);
-  } while ((r == -1) && (error = SOCKERRNO) &&
-           (error != EINVAL) && error_not_EINTR &&
-           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
+    if (r != -1)
+      break;
+    error = SOCKERRNO;
+    if ((error == EINVAL) || error_is_EINTR)
+      break;
+    if (timeout_ms > 0) {
+      pending_ms = timeout_ms - elapsed_ms;
+      if (pending_ms <= 0)
+        break;
+    }
+  } while (r == -1);
 
   if (r < 0)
     return -1;
@@ -263,14 +286,26 @@
   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 
   do {
-    if (ptimeout) {
+    if (timeout_ms > 0) {
       pending_tv.tv_sec = pending_ms / 1000;
       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
     }
+    else if (!timeout_ms) {
+      pending_tv.tv_sec = 0;
+      pending_tv.tv_usec = 0;
+    }
     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
-  } while ((r == -1) && (error = SOCKERRNO) &&
-           (error != EINVAL) && (error != EBADF) && error_not_EINTR &&
-           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
+    if (r != -1)
+      break;
+    error = SOCKERRNO;
+    if ((error == EINVAL) || (error == EBADF) || error_is_EINTR)
+      break;
+    if (timeout_ms > 0) {
+      pending_ms = timeout_ms - elapsed_ms;
+      if (pending_ms <= 0)
+        break;
+    }
+  } while (r == -1);
 
   if (r < 0)
     return -1;
@@ -343,18 +378,35 @@
     return r;
   }
 
-  pending_ms = timeout_ms;
-  initial_tv = curlx_tvnow();
+  /* Avoid initial timestamp, avoid gettimeofday() call, when elapsed
+     time in this function does not need to be measured. This happens
+     when function is called with a zero timeout or a negative timeout
+     value indicating a blocking call should be performed. */
+
+  if (timeout_ms > 0) {
+    pending_ms = timeout_ms;
+    initial_tv = curlx_tvnow();
+  }
 
 #ifdef HAVE_POLL_FINE
 
   do {
     if (timeout_ms < 0)
       pending_ms = -1;
+    else if (!timeout_ms)
+      pending_ms = 0;
     r = poll(ufds, nfds, pending_ms);
-  } while ((r == -1) && (error = SOCKERRNO) &&
-           (error != EINVAL) && error_not_EINTR &&
-           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
+    if (r != -1)
+      break;
+    error = SOCKERRNO;
+    if ((error == EINVAL) || error_is_EINTR)
+      break;
+    if (timeout_ms > 0) {
+      pending_ms = timeout_ms - elapsed_ms;
+      if (pending_ms <= 0)
+        break;
+    }
+  } while (r == -1);
 
 #else  /* HAVE_POLL_FINE */
 
@@ -384,14 +436,26 @@
   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 
   do {
-    if (ptimeout) {
+    if (timeout_ms > 0) {
       pending_tv.tv_sec = pending_ms / 1000;
       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
     }
+    else if (!timeout_ms) {
+      pending_tv.tv_sec = 0;
+      pending_tv.tv_usec = 0;
+    }
     r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
-  } while ((r == -1) && (error = SOCKERRNO) &&
-           (error != EINVAL) && (error != EBADF) && error_not_EINTR &&
-           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
+    if (r != -1)
+      break;
+    error = SOCKERRNO;
+    if ((error == EINVAL) || (error == EBADF) || error_is_EINTR)
+      break;
+    if (timeout_ms > 0) {
+      pending_ms = timeout_ms - elapsed_ms;
+      if (pending_ms <= 0)
+        break;
+    }
+  } while (r == -1);
 
   if (r < 0)
     return -1;
@@ -481,8 +545,16 @@
     return r;
   }
 
-  pending_ms = timeout_ms;
-  initial_tv = curlx_tvnow();
+  /* Avoid initial timestamp, avoid gettimeofday() call, when elapsed
+     time in this function does not need to be measured. This happens
+     when function is called with a zero timeout in the timeval struct
+     referenced argument or when a NULL pointer is received as timeval
+     reference indicating a blocking call should be performed. */
+
+  if (timeout_ms > 0) {
+    pending_ms = timeout_ms;
+    initial_tv = curlx_tvnow();
+  }
 
 #ifdef HAVE_POLL_FINE
 
@@ -530,10 +602,20 @@
   do {
     if (timeout_ms < 0)
       pending_ms = -1;
+    else if (!timeout_ms)
+      pending_ms = 0;
     r = poll(poll_fds, poll_nfds, pending_ms);
-  } while ((r == -1) && (error = SOCKERRNO) &&
-           (error != EINVAL) && error_not_EINTR &&
-           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
+    if (r != -1)
+      break;
+    error = SOCKERRNO;
+    if ((error == EINVAL) || error_is_EINTR)
+      break;
+    if (timeout_ms > 0) {
+      pending_ms = timeout_ms - elapsed_ms;
+      if (pending_ms <= 0)
+        break;
+    }
+  } while (r == -1);
 
   if (r < 0)
     ret = -1;
@@ -583,14 +665,26 @@
   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 
   do {
-    if (ptimeout) {
+    if (timeout_ms > 0) {
       pending_tv.tv_sec = pending_ms / 1000;
       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
     }
+    else if (!timeout_ms) {
+      pending_tv.tv_sec = 0;
+      pending_tv.tv_usec = 0;
+    }
     r = select(nfds, fds_read, fds_write, fds_excep, ptimeout);
-  } while ((r == -1) && (error = SOCKERRNO) &&
-           (error != EINVAL) && (error != EBADF) && error_not_EINTR &&
-           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
+    if (r != -1)
+      break;
+    error = SOCKERRNO;
+    if ((error == EINVAL) || (error == EBADF) || error_is_EINTR)
+      break;
+    if (timeout_ms > 0) {
+      pending_ms = timeout_ms - elapsed_ms;
+      if (pending_ms <= 0)
+        break;
+    }
+  } while (r == -1);
 
   if (r < 0)
     ret = -1;