diff -Naurd curl/configure.ac curl-hires/configure.ac
--- curl/configure.ac
+++ curl-hires/configure.ac
@@ -2002,6 +2002,7 @@
 CURL_CHECK_FUNC_IOCTLSOCKET
 CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL
 CURL_CHECK_FUNC_LOCALTIME_R
+CURL_CHECK_FUNC_SETITIMER
 CURL_CHECK_FUNC_SETSOCKOPT
 CURL_CHECK_FUNC_SIGACTION
 CURL_CHECK_FUNC_SIGINTERRUPT
diff -Naurd curl/lib/connect.c curl-hires/lib/connect.c
--- curl/lib/connect.c
+++ curl-hires/lib/connect.c
@@ -23,6 +23,11 @@
 
 #include "setup.h"
 
+#ifdef HAVE_SETITIMER
+#include <setjmp.h>
+#include <signal.h>
+typedef void (*sighandler_t)(int);
+#endif
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
@@ -117,6 +122,17 @@
                 long timeout_ms,
                 bool *connected);
 
+#ifdef HAVE_SETITIMER
+extern sigjmp_buf curl_jmpenv;
+
+void get_alarm(int sig)
+{
+  siglongjmp(curl_jmpenv, 1);
+  return;
+}
+#endif
+
+
 /*
  * Curl_timeleft() returns the amount of milliseconds left allowed for the
  * transfer/connection. If the value is negative, the timeout time has already
@@ -729,6 +745,15 @@
 #ifdef ENABLE_IPV6
   struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr;
 #endif
+#ifdef HAVE_SETITIMER
+  sighandler_t old_alrm;
+  struct itimerval alarm = {
+    .it_interval = {
+      .tv_sec = 0,
+      .tv_usec = 0
+    }
+  };
+#endif
 
   /*
    * The Curl_sockaddr_ex structure is basically libcurl's external API
@@ -832,12 +857,41 @@
   /* set socket non-blocking */
   Curl_nonblock(sockfd, TRUE);
 
+#ifdef HAVE_SETITIMER
+  if (timeout_ms) {
+    if (sigsetjmp(curl_jmpenv, 1)) {
+
+      signal(SIGALRM, old_alrm);
+      infof(data, "Timeout\n");
+      sclose(sockfd);
+      return CURL_SOCKET_BAD;
+
+    }
+  }
+
+  old_alrm = signal(SIGALRM, get_alarm);
+  if (timeout_ms) {
+    alarm.it_value.tv_sec = timeout_ms/1000L;
+    alarm.it_value.tv_usec = (timeout_ms%1000L) * 1000L;
+    setitimer(ITIMER_REAL, &alarm, NULL);
+  }
+#endif
+
   /* Connect TCP sockets, bind UDP */
   if(conn->socktype == SOCK_STREAM)
     rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
   else
     rc = 0;
 
+#ifdef HAVE_SETITIMER
+  if (timeout_ms) {
+    alarm.it_value.tv_sec = 0;
+    alarm.it_value.tv_usec = 0;
+    setitimer(ITIMER_REAL, &alarm, NULL);
+  }
+  signal(SIGALRM, old_alrm);
+#endif
+
   if(-1 == rc) {
     error = SOCKERRNO;
 
diff -Naurd curl/lib/hostip.c curl-hires/lib/hostip.c
--- curl/lib/hostip.c
+++ curl-hires/lib/hostip.c
@@ -552,7 +552,20 @@
 #endif /* HAVE_SIGNAL */
 #endif /* HAVE_SIGACTION */
   volatile long timeout;
+#ifdef HAVE_SETITIMER
+  struct itimerval prev_alarm = {
+    .it_interval = {
+      .tv_sec = 0,
+      .tv_usec = 0
+    }, 
+    .it_value = {
+      .tv_sec = 0,
+      .tv_usec = 0
+    }
+  };
+#else
   unsigned int prev_alarm=0;
+#endif
   struct SessionHandle *data = conn->data;
 #endif /* USE_ALARM_TIMEOUT */
   int rc;
@@ -566,10 +579,12 @@
   else
     timeout = timeoutms;
 
+#ifndef HAVE_SETITIMER
   if(timeout && timeout < 1000)
     /* The alarm() function only provides integer second resolution, so if
        we want to wait less than one second we must bail out already now. */
     return CURLRESOLV_TIMEDOUT;
+#endif
 
   if (timeout > 0) {
     /* This allows us to time-out from the name resolver, as the timeout
@@ -603,9 +618,23 @@
 #endif
 #endif /* HAVE_SIGACTION */
 
+#ifdef HAVE_SETITIMER
+    do {
+      struct itimerval alarm = {
+        .it_interval = {
+          .tv_sec = 0,
+          .tv_usec = 0
+        }
+      };
+      alarm.it_value.tv_sec = timeout/1000L;
+      alarm.it_value.tv_usec = (timeout%1000L) * 1000L;
+      setitimer(ITIMER_REAL, &alarm, &prev_alarm);
+    } while(0);
+#else
     /* alarm() makes a signal get sent when the timeout fires off, and that
        will abort system calls */
     prev_alarm = alarm((unsigned int) (timeout/1000L));
+#endif
   }
 
 #else
@@ -640,6 +669,45 @@
 
     /* switch back the alarm() to either zero or to what it was before minus
        the time we spent until now! */
+#ifdef HAVE_SETITIMER
+    if(prev_alarm.it_value.tv_sec || prev_alarm.it_value.tv_usec) {
+      /* there was an alarm() set before us, now put it back */
+      unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
+    
+      struct itimerval alarm_set = {
+        .it_interval = {
+          .tv_usec = 0,
+          .tv_sec = 0
+        }
+      };
+
+      alarm_set.it_value.tv_sec = prev_alarm.it_value.tv_sec - elapsed_ms/1000L;
+
+      if (elapsed_ms%1000L > prev_alarm.it_value.tv_usec/1000L) {
+        alarm_set.it_value.tv_sec--;
+        alarm_set.it_value.tv_usec = prev_alarm.it_value.tv_usec +
+                                     (1000L - elapsed_ms%1000L) * 1000L;
+      } else {
+        alarm_set.it_value.tv_usec = prev_alarm.it_value.tv_usec -
+                                     (elapsed_ms%1000L) * 1000L;
+      }
+
+      setitimer(ITIMER_REAL, &alarm_set, NULL);
+    } else {
+      struct itimerval alarm = {
+        .it_interval = {
+          .tv_sec = 0,
+          .tv_usec = 0
+        },
+        .it_value = {
+          .tv_sec = 0,
+          .tv_usec = 0
+        }
+      };
+
+      setitimer(ITIMER_REAL, &alarm, NULL);
+    }
+#else
     if(prev_alarm) {
       /* there was an alarm() set before us, now put it back */
       unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
@@ -662,6 +730,7 @@
     }
     else
       alarm(0); /* just shut it off */
+#endif
   }
 #endif /* USE_ALARM_TIMEOUT */
 
diff -Naurd curl/lib/transfer.c curl-hires/lib/transfer.c
--- curl/lib/transfer.c
+++ curl-hires/lib/transfer.c
@@ -1800,6 +1800,7 @@
   struct SessionHandle *data = conn->data;
   struct SingleRequest *k = &data->req;
   bool done=FALSE;
+  long milliseconds_step = 1000;
 
   if((conn->sockfd == CURL_SOCKET_BAD) &&
      (conn->writesockfd == CURL_SOCKET_BAD))
@@ -1847,13 +1848,23 @@
     if(k->keepon & KEEP_WRITE_PAUSE)
       fd_write = CURL_SOCKET_BAD;
 
+    if(data->set.timeout) {
+      milliseconds_step = data->set.timeout - Curl_tvdiff(k->now, k->start);
+
+      if (milliseconds_step > 1000)
+        milliseconds_step = 1000;
+
+      if (milliseconds_step < 0)
+        milliseconds_step = 0;
+    }
+
     /* The *_HOLD and *_PAUSE logic is necessary since even though there might
        be no traffic during the select interval, we still call
        Curl_readwrite() for the timeout case and if we limit transfer speed we
        must make sure that this function doesn't transfer anything while in
        HOLD status. */
 
-    switch (Curl_socket_ready(fd_read, fd_write, 1000)) {
+    switch (Curl_socket_ready(fd_read, fd_write, milliseconds_step)) {
     case -1: /* select() error, stop reading */
 #ifdef EINTR
       /* The EINTR is not serious, and it seems you might get this more
diff -Naurd curl/m4/curl-functions.m4 curl-hires/m4/curl-functions.m4
--- curl/m4/curl-functions.m4
+++ curl-hires/m4/curl-functions.m4
@@ -409,6 +409,92 @@
 ])
 
 
+dnl CURL_CHECK_FUNC_SETITIMER
+dnl -------------------------------------------------
+dnl Verify if setitimer is available, prototyped, and
+dnl can be compiled. If all of these are true, and
+dnl usage has not been previously disallowed with
+dnl shell variable curl_disallow_setitimer, then
+dnl HAVE_SETITIMER will be defined.
+
+AC_DEFUN([CURL_CHECK_FUNC_SETITIMER], [
+  AC_REQUIRE([CURL_INCLUDES_TIME])dnl
+  #
+  tst_links_setitimer="unknown"
+  tst_proto_setitimer="unknown"
+  tst_compi_setitimer="unknown"
+  tst_allow_setitimer="unknown"
+  #
+  AC_MSG_CHECKING([if setitimer can be linked])
+  AC_LINK_IFELSE([
+    AC_LANG_FUNC_LINK_TRY([setitimer])
+  ],[
+    AC_MSG_RESULT([yes])
+    tst_links_setitimer="yes"
+  ],[
+    AC_MSG_RESULT([no])
+    tst_links_setitimer="no"
+  ])
+  #
+  if test "$tst_links_setitimer" = "yes"; then
+    AC_MSG_CHECKING([if setitimer is prototyped])
+    AC_EGREP_CPP([setitimer],[
+      $curl_includes_time
+    ],[
+      AC_MSG_RESULT([yes])
+      tst_proto_setitimer="yes"
+    ],[
+      AC_MSG_RESULT([no])
+      tst_proto_setitimer="no"
+    ])
+  fi
+  #
+  if test "$tst_proto_setitimer" = "yes"; then
+    AC_MSG_CHECKING([if setitimer is compilable])
+    AC_COMPILE_IFELSE([
+      AC_LANG_PROGRAM([[
+        $curl_includes_time
+      ]],[[
+        struct itimerval set_alarm;
+        if(0 != setitimer(ITIMER_REAL, &set_alarm, NULL))
+          return 1;
+      ]])
+    ],[
+      AC_MSG_RESULT([yes])
+      tst_compi_setitimer="yes"
+    ],[
+      AC_MSG_RESULT([no])
+      tst_compi_setitimer="no"
+    ])
+  fi
+  #
+  if test "$tst_compi_setitimer" = "yes"; then
+    AC_MSG_CHECKING([if setitimer usage allowed])
+    if test "x$curl_disallow_setitimer" != "xyes"; then
+      AC_MSG_RESULT([yes])
+      tst_allow_setitimer="yes"
+    else
+      AC_MSG_RESULT([no])
+      tst_allow_setitimer="no"
+    fi
+  fi
+  #
+  AC_MSG_CHECKING([if setitimer might be used])
+  if test "$tst_links_setitimer" = "yes" &&
+     test "$tst_proto_setitimer" = "yes" &&
+     test "$tst_compi_setitimer" = "yes" &&
+     test "$tst_allow_setitimer" = "yes"; then
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_SETITIMER, 1,
+      [Define to 1 if you have the setitimer function.])
+    ac_cv_func_setitimer="yes"
+  else
+    AC_MSG_RESULT([no])
+    ac_cv_func_setitimer="no"
+  fi
+])
+
+
 dnl CURL_CHECK_FUNC_ALARM
 dnl -------------------------------------------------
 dnl Verify if alarm is available, prototyped, and
