|
|
777c761 |
From 4db4a1313e2992ffb77949f4fbd7fff16ffceaee Mon Sep 17 00:00:00 2001
|
|
|
777c761 |
From: Adam Jackson <ajax@redhat.com>
|
|
|
777c761 |
Date: Wed, 10 Dec 2008 16:13:20 -0500
|
|
|
777c761 |
Subject: [PATCH] xsync: Fix wakeup storm in idletime counter.
|
|
|
777c761 |
|
|
|
777c761 |
Wakeup scheduling only considered the threshold values, and not whether
|
|
|
777c761 |
the trigger was edge or level.
|
|
|
777c761 |
---
|
|
|
777c761 |
Xext/sync.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
|
|
|
777c761 |
1 files changed, 41 insertions(+), 10 deletions(-)
|
|
|
777c761 |
|
|
|
777c761 |
diff --git a/Xext/sync.c b/Xext/sync.c
|
|
|
777c761 |
index d6b8c27..4d159d2 100644
|
|
|
777c761 |
--- a/Xext/sync.c
|
|
|
777c761 |
+++ b/Xext/sync.c
|
|
|
777c761 |
@@ -2323,7 +2323,7 @@ SyncInitServerTime(void)
|
|
|
777c761 |
* IDLETIME implementation
|
|
|
777c761 |
*/
|
|
|
777c761 |
|
|
|
777c761 |
-static pointer IdleTimeCounter;
|
|
|
777c761 |
+static SyncCounter *IdleTimeCounter;
|
|
|
777c761 |
static XSyncValue *pIdleTimeValueLess;
|
|
|
777c761 |
static XSyncValue *pIdleTimeValueGreater;
|
|
|
777c761 |
|
|
|
777c761 |
@@ -2335,38 +2335,69 @@ IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return)
|
|
|
777c761 |
}
|
|
|
777c761 |
|
|
|
777c761 |
static void
|
|
|
777c761 |
-IdleTimeBlockHandler (pointer env,
|
|
|
777c761 |
- struct timeval **wt,
|
|
|
777c761 |
- pointer LastSelectMask)
|
|
|
777c761 |
+IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask)
|
|
|
777c761 |
{
|
|
|
777c761 |
- XSyncValue idle;
|
|
|
777c761 |
+ XSyncValue idle, old_idle;
|
|
|
777c761 |
+ SyncTriggerList *list = IdleTimeCounter->pTriglist;
|
|
|
777c761 |
+ SyncTrigger *trig;
|
|
|
777c761 |
|
|
|
777c761 |
if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
|
|
|
777c761 |
return;
|
|
|
777c761 |
|
|
|
777c761 |
+ old_idle = IdleTimeCounter->value;
|
|
|
777c761 |
IdleTimeQueryValue (NULL, &idle);
|
|
|
777c761 |
+ IdleTimeCounter->value = idle; /* push, so CheckTrigger works */
|
|
|
777c761 |
|
|
|
777c761 |
if (pIdleTimeValueLess &&
|
|
|
777c761 |
XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))
|
|
|
777c761 |
{
|
|
|
777c761 |
- AdjustWaitForDelay (wt, 0);
|
|
|
777c761 |
+ /*
|
|
|
777c761 |
+ * We've been idle for less than the threshold value, and someone
|
|
|
777c761 |
+ * wants to know about that, but now we need to know whether they
|
|
|
777c761 |
+ * want level or edge trigger. Check the trigger list against the
|
|
|
777c761 |
+ * current idle time, and if any succeed, bomb out of select()
|
|
|
777c761 |
+ * immediately so we can reschedule.
|
|
|
777c761 |
+ */
|
|
|
777c761 |
+
|
|
|
777c761 |
+ for (list = IdleTimeCounter->pTriglist; list; list = list->next) {
|
|
|
777c761 |
+ trig = list->pTrigger;
|
|
|
777c761 |
+ if (trig->CheckTrigger(trig, old_idle)) {
|
|
|
777c761 |
+ AdjustWaitForDelay(wt, 0);
|
|
|
777c761 |
+ break;
|
|
|
777c761 |
+ }
|
|
|
777c761 |
+ }
|
|
|
777c761 |
}
|
|
|
777c761 |
else if (pIdleTimeValueGreater)
|
|
|
777c761 |
{
|
|
|
777c761 |
- unsigned long timeout = 0;
|
|
|
777c761 |
+ /*
|
|
|
777c761 |
+ * There's a threshold in the positive direction. If we've been
|
|
|
777c761 |
+ * idle less than it, schedule a wakeup for sometime in the future.
|
|
|
777c761 |
+ * If we've been idle more than it, and someone wants to know about
|
|
|
777c761 |
+ * that level-triggered, schedule an immediate wakeup.
|
|
|
777c761 |
+ */
|
|
|
777c761 |
+ unsigned long timeout = -1;
|
|
|
777c761 |
|
|
|
777c761 |
- if (XSyncValueLessThan (idle, *pIdleTimeValueGreater))
|
|
|
777c761 |
- {
|
|
|
777c761 |
+ if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) {
|
|
|
777c761 |
XSyncValue value;
|
|
|
777c761 |
Bool overflow;
|
|
|
777c761 |
|
|
|
777c761 |
XSyncValueSubtract (&value, *pIdleTimeValueGreater,
|
|
|
777c761 |
idle, &overflow);
|
|
|
777c761 |
- timeout = XSyncValueLow32 (value);
|
|
|
777c761 |
+ timeout = min(timeout, XSyncValueLow32 (value));
|
|
|
777c761 |
+ } else {
|
|
|
777c761 |
+ for (list = IdleTimeCounter->pTriglist; list; list = list->next) {
|
|
|
777c761 |
+ trig = list->pTrigger;
|
|
|
777c761 |
+ if (trig->CheckTrigger(trig, old_idle)) {
|
|
|
777c761 |
+ timeout = min(timeout, 0);
|
|
|
777c761 |
+ break;
|
|
|
777c761 |
+ }
|
|
|
777c761 |
+ }
|
|
|
777c761 |
}
|
|
|
777c761 |
|
|
|
777c761 |
AdjustWaitForDelay (wt, timeout);
|
|
|
777c761 |
}
|
|
|
777c761 |
+
|
|
|
777c761 |
+ IdleTimeCounter->value = old_idle; /* pop */
|
|
|
777c761 |
}
|
|
|
777c761 |
|
|
|
777c761 |
static void
|
|
|
777c761 |
--
|
|
|
777c761 |
1.6.0.3
|
|
|
777c761 |
|