summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2008-12-10 16:13:20 -0500
committerAdam Jackson <ajax@redhat.com>2008-12-11 10:31:48 -0500
commit1f4fb0225b278d1cf4145aebeb0bdd23dc8f62d5 (patch)
tree56ccd03a85d24c8d715f56c404dcbe464fff35f7
parent1a99110f0c221b79045ea26d61c4a1ec1e0d7341 (diff)
xsync: Fix wakeup storm in idletime counter.
Wakeup scheduling only considered the threshold values, and not whether the trigger was edge or level. See also: https://bugzilla.redhat.com/show_bug.cgi?id=474586 http://svn.gnome.org/viewvc/gnome-screensaver/trunk/src/test-idle-ext.c?view=markup
-rw-r--r--Xext/sync.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/Xext/sync.c b/Xext/sync.c
index 88fc03d03..d9e66b3f4 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -2281,7 +2281,7 @@ SyncInitServerTime(void)
2281 * IDLETIME implementation 2281 * IDLETIME implementation
2282 */ 2282 */
2283 2283
2284static pointer IdleTimeCounter; 2284static SyncCounter *IdleTimeCounter;
2285static XSyncValue *pIdleTimeValueLess; 2285static XSyncValue *pIdleTimeValueLess;
2286static XSyncValue *pIdleTimeValueGreater; 2286static XSyncValue *pIdleTimeValueGreater;
2287 2287
@@ -2293,38 +2293,69 @@ IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return)
2293} 2293}
2294 2294
2295static void 2295static void
2296IdleTimeBlockHandler (pointer env, 2296IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask)
2297 struct timeval **wt,
2298 pointer LastSelectMask)
2299{ 2297{
2300 XSyncValue idle; 2298 XSyncValue idle, old_idle;
2299 SyncTriggerList *list = IdleTimeCounter->pTriglist;
2300 SyncTrigger *trig;
2301 2301
2302 if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 2302 if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
2303 return; 2303 return;
2304 2304
2305 old_idle = IdleTimeCounter->value;
2305 IdleTimeQueryValue (NULL, &idle); 2306 IdleTimeQueryValue (NULL, &idle);
2307 IdleTimeCounter->value = idle; /* push, so CheckTrigger works */
2306 2308
2307 if (pIdleTimeValueLess && 2309 if (pIdleTimeValueLess &&
2308 XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) 2310 XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))
2309 { 2311 {
2310 AdjustWaitForDelay (wt, 0); 2312 /*
2313 * We've been idle for less than the threshold value, and someone
2314 * wants to know about that, but now we need to know whether they
2315 * want level or edge trigger. Check the trigger list against the
2316 * current idle time, and if any succeed, bomb out of select()
2317 * immediately so we can reschedule.
2318 */
2319
2320 for (list = IdleTimeCounter->pTriglist; list; list = list->next) {
2321 trig = list->pTrigger;
2322 if (trig->CheckTrigger(trig, old_idle)) {
2323 AdjustWaitForDelay(wt, 0);
2324 break;
2325 }
2326 }
2311 } 2327 }
2312 else if (pIdleTimeValueGreater) 2328 else if (pIdleTimeValueGreater)
2313 { 2329 {
2314 unsigned long timeout = 0; 2330 /*
2331 * There's a threshold in the positive direction. If we've been
2332 * idle less than it, schedule a wakeup for sometime in the future.
2333 * If we've been idle more than it, and someone wants to know about
2334 * that level-triggered, schedule an immediate wakeup.
2335 */
2336 unsigned long timeout = -1;
2315 2337
2316 if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) 2338 if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) {
2317 {
2318 XSyncValue value; 2339 XSyncValue value;
2319 Bool overflow; 2340 Bool overflow;
2320 2341
2321 XSyncValueSubtract (&value, *pIdleTimeValueGreater, 2342 XSyncValueSubtract (&value, *pIdleTimeValueGreater,
2322 idle, &overflow); 2343 idle, &overflow);
2323 timeout = XSyncValueLow32 (value); 2344 timeout = min(timeout, XSyncValueLow32 (value));
2345 } else {
2346 for (list = IdleTimeCounter->pTriglist; list; list = list->next) {
2347 trig = list->pTrigger;
2348 if (trig->CheckTrigger(trig, old_idle)) {
2349 timeout = min(timeout, 0);
2350 break;
2351 }
2352 }
2324 } 2353 }
2325 2354
2326 AdjustWaitForDelay (wt, timeout); 2355 AdjustWaitForDelay (wt, timeout);
2327 } 2356 }
2357
2358 IdleTimeCounter->value = old_idle; /* pop */
2328} 2359}
2329 2360
2330static void 2361static void