diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index ad081ec17fbb9bc066a5fb3cb1db4c1922ed781f..f8c60a387f5674c0af7515f9e7e913dd33693047 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -68,6 +68,19 @@ lws_free_wsi(struct lws *wsi)
 	lws_free(wsi);
 }
 
+
+static void
+lws_remove_from_timeout_list(struct lws *wsi)
+{
+	if (!wsi->timeout_list_prev)
+		return;
+
+	*wsi->timeout_list_prev = wsi->timeout_list;
+	wsi->timeout_list_prev = NULL;
+	wsi->timeout_list = NULL;
+}
+
+
 void
 lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
 {
@@ -234,6 +247,7 @@ just_kill_connection:
 	 * delete socket from the internal poll list if still present
 	 */
 	lws_ssl_remove_wsi_from_buffered_list(wsi);
+	lws_remove_from_timeout_list(wsi);
 
 	/* checking return redundant since we anyway close */
 	remove_wsi_socket_from_fds(wsi);
@@ -563,8 +577,19 @@ lws_set_timeout(struct lws *wsi, enum pending_timeout reason, int secs)
 
 	time(&now);
 
+	if (!wsi->pending_timeout) {
+		wsi->timeout_list = wsi->context->timeout_list;
+		if (wsi->timeout_list)
+			wsi->timeout_list->timeout_list_prev = &wsi->timeout_list;
+		wsi->timeout_list_prev = &wsi->context->timeout_list;
+		*wsi->timeout_list_prev = wsi;
+	}
+
 	wsi->pending_timeout_limit = now + secs;
 	wsi->pending_timeout = reason;
+
+	if (!reason)
+		lws_remove_from_timeout_list(wsi);
 }
 
 
@@ -1144,7 +1169,7 @@ lws_parse_uri(char *p, const char **prot, const char **ads, int *port, const cha
 		*port = 80;
 	else if (!strcmp(*prot, "https") || !strcmp(*prot, "wss"))
 		*port = 443;
-	
+
 	while (*p && *p != ':' && *p != '/')
 		p++;
 	if (*p == ':') {
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 92ea713f05d82821a95c0616cd07b95d06b658b9..7a16cb50fa7b02a610ab063d147822ce96ab091c 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -290,7 +290,7 @@ extern "C" {
 #define LWS_MAX_PROTOCOLS 5
 #endif
 #ifndef LWS_MAX_EXTENSIONS_ACTIVE
-#define LWS_MAX_EXTENSIONS_ACTIVE 3
+#define LWS_MAX_EXTENSIONS_ACTIVE 2
 #endif
 #ifndef LWS_MAX_EXT_OFFERS
 #define LWS_MAX_EXT_OFFERS 8
@@ -522,6 +522,8 @@ struct lws_context {
 	const char *iface;
 	const struct lws_token_limits *token_limits;
 	void *user_space;
+	struct lws *timeout_list;
+
 #ifndef LWS_NO_SERVER
 	struct lws *wsi_listening;
 #endif
@@ -907,6 +909,8 @@ struct lws {
 
 	struct lws_context *context;
 	const struct lws_protocols *protocol;
+	struct lws *timeout_list;
+	struct lws **timeout_list_prev;
 	void *user_space;
 	/* rxflow handling */
 	unsigned char *rxflow_buffer;
@@ -929,7 +933,6 @@ struct lws {
 	lws_sockfd_type sock;
 
 	/* ints */
-	enum lws_pending_protocol_send pps;
 	int position_in_fds_table;
 	int rxflow_len;
 	int rxflow_pos;
@@ -962,6 +965,7 @@ struct lws {
 	char lws_rx_parse_state; /* enum lws_rx_parse_state */
 	char rx_frame_type; /* enum lws_write_protocol */
 	char pending_timeout; /* enum pending_timeout */
+	char pps; /* enum lws_pending_protocol_send */
 };
 
 LWS_EXTERN int log_level;
diff --git a/lib/service.c b/lib/service.c
index 4544b5010fc21674b32d838238f65724c3deaecf..9ddbeaea8c4bcb5b209e447a4fa168a0965f194c 100644
--- a/lib/service.c
+++ b/lib/service.c
@@ -298,8 +298,7 @@ lws_service_timeout_check(struct lws *wsi, unsigned int sec)
 	 * if extensions want in on it (eg, we are a mux parent)
 	 * give them a chance to service child timeouts
 	 */
-	if (lws_ext_cb_active(wsi, LWS_EXT_CB_1HZ,
-					     NULL, sec) < 0)
+	if (lws_ext_cb_active(wsi, LWS_EXT_CB_1HZ, NULL, sec) < 0)
 		return 0;
 
 	if (!wsi->pending_timeout)
@@ -380,7 +379,6 @@ lws_service_fd(struct lws_context *context, struct lws_pollfd *pollfd)
 	struct lws_tokens eff_buf;
 	unsigned int pending = 0;
 	char draining_flow = 0;
-	lws_sockfd_type mfd;
 	int timed_out = 0;
 	struct lws *wsi;
 	time_t now;
@@ -410,18 +408,15 @@ lws_service_fd(struct lws_context *context, struct lws_pollfd *pollfd)
 		if (pollfd)
 			our_fd = pollfd->fd;
 
-		for (n = 0; n < context->fds_count; n++) {
-			mfd = context->fds[n].fd;
-			wsi = wsi_from_fd(context, mfd);
-			if (!wsi)
-				continue;
-
+		wsi = context->timeout_list;
+		while (wsi) {
 			if (lws_service_timeout_check(wsi, (unsigned int)now))
 				/* he did time out... */
-				if (mfd == our_fd)
+				if (wsi->sock == our_fd)
 					/* it was the guy we came to service! */
 					timed_out = 1;
 					/* he's gone, no need to mark as handled */
+			wsi = wsi->timeout_list;
 		}
 	}