]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
multi: more efficient pollfd count for poll
authorStefan Eissing <stefan@eissing.org>
Mon, 4 Sep 2023 07:55:27 +0000 (09:55 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 4 Sep 2023 17:50:22 +0000 (19:50 +0200)
- do not use separate pollfds for sockets that have POLLIN+POLLOUT

Closes #11792

lib/multi.c
lib/multiif.h

index dab207a6f32bf16a509398deb772442359f2f0be..bb57dbceee26d3e5b459d395205d4e7e6afb472f 100644 (file)
@@ -1110,8 +1110,7 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
   if(multi->in_callback)
     return CURLM_RECURSIVE_API_CALL;
 
-  data = multi->easyp;
-  while(data) {
+  for(data = multi->easyp; data; data = data->next) {
     int bitmap;
 #ifdef __clang_analyzer_
     /* to prevent "The left operand of '>=' is a garbage value" warnings */
@@ -1120,30 +1119,21 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
     bitmap = multi_getsock(data, sockbunch);
 
     for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
-      curl_socket_t s = CURL_SOCKET_BAD;
-
-      if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK(sockbunch[i])) {
+      if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
         if(!FDSET_SOCK(sockbunch[i]))
           /* pretend it doesn't exist */
           continue;
-        FD_SET(sockbunch[i], read_fd_set);
-        s = sockbunch[i];
+        if(bitmap & GETSOCK_READSOCK(i))
+          FD_SET(sockbunch[i], read_fd_set);
+        if(bitmap & GETSOCK_WRITESOCK(i))
+          FD_SET(sockbunch[i], write_fd_set);
+        if((int)sockbunch[i] > this_max_fd)
+          this_max_fd = (int)sockbunch[i];
       }
-      if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK(sockbunch[i])) {
-        if(!FDSET_SOCK(sockbunch[i]))
-          /* pretend it doesn't exist */
-          continue;
-        FD_SET(sockbunch[i], write_fd_set);
-        s = sockbunch[i];
-      }
-      if(s == CURL_SOCKET_BAD)
-        /* this socket is unused, break out of loop */
+      else {
         break;
-      if((int)s > this_max_fd)
-        this_max_fd = (int)s;
+      }
     }
-
-    data = data->next; /* check next handle */
   }
 
   *max_fd = this_max_fd;
@@ -1206,27 +1196,17 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
     return CURLM_BAD_FUNCTION_ARGUMENT;
 
   /* Count up how many fds we have from the multi handle */
-  data = multi->easyp;
-  while(data) {
+  for(data = multi->easyp; data; data = data->next) {
     bitmap = multi_getsock(data, sockbunch);
 
-    for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
-      curl_socket_t s = CURL_SOCKET_BAD;
-
-      if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
-        ++nfds;
-        s = sockbunch[i];
-      }
-      if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
+    for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
+      if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
         ++nfds;
-        s = sockbunch[i];
       }
-      if(s == CURL_SOCKET_BAD) {
+      else {
         break;
       }
     }
-
-    data = data->next; /* check next handle */
   }
 
   /* If the internally desired timeout is actually shorter than requested from
@@ -1266,49 +1246,42 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
 
   if(curlfds) {
     /* Add the curl handles to our pollfds first */
-    data = multi->easyp;
-    while(data) {
+    for(data = multi->easyp; data; data = data->next) {
       bitmap = multi_getsock(data, sockbunch);
 
       for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
-        curl_socket_t s = CURL_SOCKET_BAD;
+        if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
+          struct pollfd *ufd = &ufds[nfds++];
 #ifdef USE_WINSOCK
-        long mask = 0;
+          long mask = 0;
 #endif
-        if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
-          s = sockbunch[i];
+          ufd->fd = sockbunch[i];
+          ufd->events = 0;
+          if(bitmap & GETSOCK_READSOCK(i)) {
 #ifdef USE_WINSOCK
-          mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
+            mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
 #endif
-          ufds[nfds].fd = s;
-          ufds[nfds].events = POLLIN;
-          ++nfds;
-        }
-        if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
-          s = sockbunch[i];
+            ufd->events |= POLLIN;
+          }
+          if(bitmap & GETSOCK_WRITESOCK(i)) {
+#ifdef USE_WINSOCK
+            mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
+            reset_socket_fdwrite(sockbunch[i]);
+#endif
+            ufd->events |= POLLOUT;
+          }
 #ifdef USE_WINSOCK
-          mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
-          reset_socket_fdwrite(s);
+          if(WSAEventSelect(sockbunch[i], multi->wsa_event, mask) != 0) {
+            if(ufds_malloc)
+              free(ufds);
+            return CURLM_INTERNAL_ERROR;
+          }
 #endif
-          ufds[nfds].fd = s;
-          ufds[nfds].events = POLLOUT;
-          ++nfds;
         }
-        /* s is only set if either being readable or writable is checked */
-        if(s == CURL_SOCKET_BAD) {
-          /* break on entry not checked for being readable or writable */
+        else {
           break;
         }
-#ifdef USE_WINSOCK
-        if(WSAEventSelect(s, multi->wsa_event, mask) != 0) {
-          if(ufds_malloc)
-            free(ufds);
-          return CURLM_INTERNAL_ERROR;
-        }
-#endif
       }
-
-      data = data->next; /* check next handle */
     }
   }
 
@@ -1417,8 +1390,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
       /* Count up all our own sockets that had activity,
          and remove them from the event. */
       if(curlfds) {
-        data = multi->easyp;
-        while(data) {
+
+        for(data = multi->easyp; data; data = data->next) {
           bitmap = multi_getsock(data, sockbunch);
 
           for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
@@ -1435,8 +1408,6 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
               break;
             }
           }
-
-          data = data->next;
         }
       }
 
@@ -2948,7 +2919,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
 
   /* walk over the sockets we got right now */
   for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
-        (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
+      (curraction & GETSOCK_MASK_RW(i));
       i++) {
     unsigned char action = CURL_POLL_NONE;
     unsigned char prevaction = 0;
index 88180bd0c88e7da9d1fb8d82b7a8cee5cbe4a7ef..7f08ecc614be913f57e9ca4fa7dd27541d63eb4a 100644 (file)
@@ -59,6 +59,9 @@ struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
 /* set the bit for the given sock number to make the bitmap for readable */
 #define GETSOCK_READSOCK(x) (1 << (x))
 
+/* mask for checking if read and/or write is set for index x */
+#define GETSOCK_MASK_RW(x) (GETSOCK_READSOCK(x)|GETSOCK_WRITESOCK(x))
+
 #ifdef DEBUGBUILD
  /*
   * Curl_multi_dump is not a stable public function, this is only meant to