OPTIM: session: don't process the whole session when only timers need a refresh

Having a global expiration timer for a task means that the tasks are regularly
woken up (at least after each expiration timer). It's totally useless and counter
productive to process the whole session upon each such wakeup, and it's fairly
easy to detect such wakeups, so let's just update the task's timer and return
to sleep when this happens.

For 100k concurrent connections with 10s of timeouts, this can save 10k wakeups
per second, which is not bad.
diff --git a/src/session.c b/src/session.c
index 55f976b..04eee61 100644
--- a/src/session.c
+++ b/src/session.c
@@ -1599,6 +1599,18 @@
 				s->rep->prod->flags |= SI_FL_NOLINGER;
 			si_shutr(s->rep->prod);
 		}
+
+		/* Once in a while we're woken up because the task expires. But
+		 * this does not necessarily mean that a timeout has been reached.
+		 * So let's not run a whole session processing if only an expiration
+		 * timeout needs to be refreshed.
+		 */
+		if (!((s->req->flags | s->rep->flags) &
+		      (CF_SHUTR|CF_READ_ACTIVITY|CF_READ_TIMEOUT|CF_SHUTW|
+		       CF_WRITE_ACTIVITY|CF_WRITE_TIMEOUT|CF_ANA_TIMEOUT)) &&
+		    !((s->si[0].flags | s->si[1].flags) & (SI_FL_EXP|SI_FL_ERR)) &&
+		    ((t->state & TASK_WOKEN_ANY) == TASK_WOKEN_TIMER))
+			goto update_exp_and_leave;
 	}
 
 	/* 1b: check for low-level errors reported at the stream interface.
@@ -2376,6 +2388,7 @@
 			}
 		}
 
+	update_exp_and_leave:
 		t->expire = tick_first(tick_first(s->req->rex, s->req->wex),
 				       tick_first(s->rep->rex, s->rep->wex));
 		if (s->req->analysers)