__decl_hathreads(extern HA_RWLOCK_T __attribute__((aligned(64))) fdcache_lock); /* global lock to protect fd_cache array */
__decl_hathreads(extern HA_SPINLOCK_T __attribute__((aligned(64))) poll_lock); /* global lock to protect poll info */
-/* Deletes an FD from the fdsets, and recomputes the maxfd limit.
+/* Deletes an FD from the fdsets.
* The file descriptor is also closed.
*/
void fd_delete(int fd);
-/* Deletes an FD from the fdsets, and recomputes the maxfd limit.
+/* Deletes an FD from the fdsets.
* The file descriptor is kept open.
*/
void fd_remove(int fd);
* still knows this FD from a possible previous round.
*/
HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
-
- HA_SPIN_LOCK(FDTAB_LOCK, &fdtab_lock);
- if (fd + 1 > maxfd)
- maxfd = fd + 1;
- HA_SPIN_UNLOCK(FDTAB_LOCK, &fdtab_lock);
}
extern struct fdtab *fdtab; /* array of all the file descriptors */
extern struct fdinfo *fdinfo; /* less-often used infos for file descriptors */
-extern int maxfd; /* # of the highest fd + 1 */
extern int totalconn; /* total # of terminated sessions */
extern int actconn; /* # of active sessions */
#define POLLRDHUP 0
#endif
+static int maxfd; /* # of the highest fd + 1 */
static unsigned int *fd_evts[2];
/* private data */
int updt_idx, en, eo;
int fds, count;
int sr, sw;
+ int old_maxfd, new_maxfd, max_add_fd;
unsigned rn, wn; /* read new, write new */
+ max_add_fd = -1;
+
/* first, scan the update list to find changes */
for (updt_idx = 0; updt_idx < fd_nbupdt; updt_idx++) {
fd = fd_updt[updt_idx];
else if ((en & ~eo) & FD_EV_POLLED_W)
hap_fd_set(fd, fd_evts[DIR_WR]);
HA_SPIN_UNLOCK(POLL_LOCK, &poll_lock);
+
+ if (fd > max_add_fd)
+ max_add_fd = fd;
}
}
+
+ /* maybe we added at least one fd larger than maxfd */
+ for (old_maxfd = maxfd; old_maxfd <= max_add_fd; ) {
+ if (HA_ATOMIC_CAS(&maxfd, &old_maxfd, max_add_fd + 1))
+ break;
+ }
+
+ /* maxfd doesn't need to be precise but it needs to cover *all* active
+ * FDs. Thus we only shrink it if we have such an opportunity. The algo
+ * is simple : look for the previous used place, try to update maxfd to
+ * point to it, abort if maxfd changed in the mean time.
+ */
+ old_maxfd = maxfd;
+ do {
+ new_maxfd = old_maxfd;
+ while (new_maxfd - 1 >= 0 && !fdtab[new_maxfd - 1].owner)
+ new_maxfd--;
+ if (new_maxfd >= old_maxfd)
+ break;
+ } while (!HA_ATOMIC_CAS(&maxfd, &old_maxfd, new_maxfd));
+
fd_nbupdt = 0;
nbfd = 0;
/* private data */
+static int maxfd; /* # of the highest fd + 1 */
static fd_set *fd_evts[2];
static THREAD_LOCAL fd_set *tmp_evts[2];
int updt_idx, en, eo;
char count;
int readnotnull, writenotnull;
+ int old_maxfd, new_maxfd, max_add_fd;
+
+ max_add_fd = -1;
/* first, scan the update list to find changes */
for (updt_idx = 0; updt_idx < fd_nbupdt; updt_idx++) {
HA_SPIN_LOCK(POLL_LOCK, &poll_lock);
if ((eo & ~en) & FD_EV_POLLED_R)
FD_CLR(fd, fd_evts[DIR_RD]);
- else if ((en & ~eo) & FD_EV_POLLED_R)
+ else if ((en & ~eo) & FD_EV_POLLED_R) {
FD_SET(fd, fd_evts[DIR_RD]);
+ if (fd > max_add_fd)
+ max_add_fd = fd;
+ }
if ((eo & ~en) & FD_EV_POLLED_W)
FD_CLR(fd, fd_evts[DIR_WR]);
- else if ((en & ~eo) & FD_EV_POLLED_W)
+ else if ((en & ~eo) & FD_EV_POLLED_W) {
FD_SET(fd, fd_evts[DIR_WR]);
+ if (fd > max_add_fd)
+ max_add_fd = fd;
+ }
+
HA_SPIN_UNLOCK(POLL_LOCK, &poll_lock);
}
}
+
+ /* maybe we added at least one fd larger than maxfd */
+ for (old_maxfd = maxfd; old_maxfd <= max_add_fd; ) {
+ if (HA_ATOMIC_CAS(&maxfd, &old_maxfd, max_add_fd + 1))
+ break;
+ }
+
+ /* maxfd doesn't need to be precise but it needs to cover *all* active
+ * FDs. Thus we only shrink it if we have such an opportunity. The algo
+ * is simple : look for the previous used place, try to update maxfd to
+ * point to it, abort if maxfd changed in the mean time.
+ */
+ old_maxfd = maxfd;
+ do {
+ new_maxfd = old_maxfd;
+ while (new_maxfd - 1 >= 0 && !fdtab[new_maxfd - 1].owner)
+ new_maxfd--;
+ if (new_maxfd >= old_maxfd)
+ break;
+ } while (!HA_ATOMIC_CAS(&maxfd, &old_maxfd, new_maxfd));
+
fd_nbupdt = 0;
/* let's restore fdset state */
struct fdtab *fdtab = NULL; /* array of all the file descriptors */
struct fdinfo *fdinfo = NULL; /* less-often used infos for file descriptors */
-int maxfd; /* # of the highest fd + 1 */
int totalconn; /* total # of terminated sessions */
int actconn; /* # of active sessions */
__decl_hathreads(HA_RWLOCK_T fdcache_lock); /* global lock to protect fd_cache array */
__decl_hathreads(HA_SPINLOCK_T poll_lock); /* global lock to protect poll info */
-/* Deletes an FD from the fdsets, and recomputes the maxfd limit.
+/* Deletes an FD from the fdsets.
* The file descriptor is also closed.
*/
static void fd_dodelete(int fd, int do_close)
close(fd);
}
HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
-
- HA_SPIN_LOCK(FDTAB_LOCK, &fdtab_lock);
- while ((maxfd-1 >= 0) && !fdtab[maxfd-1].owner)
- maxfd--;
- HA_SPIN_UNLOCK(FDTAB_LOCK, &fdtab_lock);
}
-/* Deletes an FD from the fdsets, and recomputes the maxfd limit.
+/* Deletes an FD from the fdsets.
* The file descriptor is also closed.
*/
void fd_delete(int fd)
fd_dodelete(fd, 1);
}
-/* Deletes an FD from the fdsets, and recomputes the maxfd limit.
+/* Deletes an FD from the fdsets.
* The file descriptor is kept open.
*/
void fd_remove(int fd)
* Initialize the previously static variables.
*/
- totalconn = actconn = maxfd = listeners = stopping = 0;
+ totalconn = actconn = listeners = stopping = 0;
killed = 0;