Wed Mar 18 05:47:41 2009 UTC ()
Pull up following revision(s) (requested by jmcneill in ticket #584):
	external/mit/xorg-server/dist/Xext/sync.c: revision 1.2
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
Source:
http://cgit.freedesktop.org/xorg/xserver/commit/?id=1f4fb0225b278d1cf4145aebeb0bdd23dc8f62d5


(snj)
diff -r1.1.1.1 -r1.1.1.1.2.1 xsrc/external/mit/xorg-server/dist/Xext/sync.c

cvs diff -r1.1.1.1 -r1.1.1.1.2.1 xsrc/external/mit/xorg-server/dist/Xext/sync.c (expand / switch to unified diff)

--- xsrc/external/mit/xorg-server/dist/Xext/sync.c 2008/07/31 19:49:32 1.1.1.1
+++ xsrc/external/mit/xorg-server/dist/Xext/sync.c 2009/03/18 05:47:41 1.1.1.1.2.1
@@ -2523,70 +2523,101 @@ SyncInitServerTime(void) @@ -2523,70 +2523,101 @@ SyncInitServerTime(void)
2523 XSyncIntToValue(&resolution, 4); 2523 XSyncIntToValue(&resolution, 4);
2524 ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, 2524 ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
2525 XSyncCounterNeverDecreases, 2525 XSyncCounterNeverDecreases,
2526 ServertimeQueryValue, ServertimeBracketValues); 2526 ServertimeQueryValue, ServertimeBracketValues);
2527 pnext_time = NULL; 2527 pnext_time = NULL;
2528} 2528}
2529 2529
2530 2530
2531 2531
2532/* 2532/*
2533 * IDLETIME implementation 2533 * IDLETIME implementation
2534 */ 2534 */
2535 2535
2536static pointer IdleTimeCounter; 2536static SyncCounter *IdleTimeCounter;
2537static XSyncValue *pIdleTimeValueLess; 2537static XSyncValue *pIdleTimeValueLess;
2538static XSyncValue *pIdleTimeValueGreater; 2538static XSyncValue *pIdleTimeValueGreater;
2539 2539
2540static void 2540static void
2541IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) 2541IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return)
2542{ 2542{
2543 CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; 2543 CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
2544 XSyncIntsToValue (pValue_return, idle, 0); 2544 XSyncIntsToValue (pValue_return, idle, 0);
2545} 2545}
2546 2546
2547static void 2547static void
2548IdleTimeBlockHandler (pointer env, 2548IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask)
2549 struct timeval **wt, 
2550 pointer LastSelectMask) 
2551{ 2549{
2552 XSyncValue idle; 2550 XSyncValue idle, old_idle;
 2551 SyncTriggerList *list = IdleTimeCounter->pTriglist;
 2552 SyncTrigger *trig;
2553 2553
2554 if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 2554 if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
2555 return; 2555 return;
2556 2556
 2557 old_idle = IdleTimeCounter->value;
2557 IdleTimeQueryValue (NULL, &idle); 2558 IdleTimeQueryValue (NULL, &idle);
 2559 IdleTimeCounter->value = idle; /* push, so CheckTrigger works */
2558 2560
2559 if (pIdleTimeValueLess && 2561 if (pIdleTimeValueLess &&
2560 XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) 2562 XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))
2561 { 2563 {
2562 AdjustWaitForDelay (wt, 0); 2564 /*
 2565 * We've been idle for less than the threshold value, and someone
 2566 * wants to know about that, but now we need to know whether they
 2567 * want level or edge trigger. Check the trigger list against the
 2568 * current idle time, and if any succeed, bomb out of select()
 2569 * immediately so we can reschedule.
 2570 */
 2571
 2572 for (list = IdleTimeCounter->pTriglist; list; list = list->next) {
 2573 trig = list->pTrigger;
 2574 if (trig->CheckTrigger(trig, old_idle)) {
 2575 AdjustWaitForDelay(wt, 0);
 2576 break;
 2577 }
 2578 }
2563 } 2579 }
2564 else if (pIdleTimeValueGreater) 2580 else if (pIdleTimeValueGreater)
2565 { 2581 {
2566 unsigned long timeout = 0; 2582 /*
 2583 * There's a threshold in the positive direction. If we've been
 2584 * idle less than it, schedule a wakeup for sometime in the future.
 2585 * If we've been idle more than it, and someone wants to know about
 2586 * that level-triggered, schedule an immediate wakeup.
 2587 */
 2588 unsigned long timeout = -1;
2567 2589
2568 if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) 2590 if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) {
2569 { 
2570 XSyncValue value; 2591 XSyncValue value;
2571 Bool overflow; 2592 Bool overflow;
2572 2593
2573 XSyncValueSubtract (&value, *pIdleTimeValueGreater, 2594 XSyncValueSubtract (&value, *pIdleTimeValueGreater,
2574 idle, &overflow); 2595 idle, &overflow);
2575 timeout = XSyncValueLow32 (value); 2596 timeout = min(timeout, XSyncValueLow32 (value));
 2597 } else {
 2598 for (list = IdleTimeCounter->pTriglist; list; list = list->next) {
 2599 trig = list->pTrigger;
 2600 if (trig->CheckTrigger(trig, old_idle)) {
 2601 timeout = min(timeout, 0);
 2602 break;
 2603 }
 2604 }
2576 } 2605 }
2577 2606
2578 AdjustWaitForDelay (wt, timeout); 2607 AdjustWaitForDelay (wt, timeout);
2579 } 2608 }
 2609
 2610 IdleTimeCounter->value = old_idle; /* pop */
2580} 2611}
2581 2612
2582static void 2613static void
2583IdleTimeWakeupHandler (pointer env, 2614IdleTimeWakeupHandler (pointer env,
2584 int rc, 2615 int rc,
2585 pointer LastSelectMask) 2616 pointer LastSelectMask)
2586{ 2617{
2587 XSyncValue idle; 2618 XSyncValue idle;
2588 2619
2589 if (!pIdleTimeValueLess && !pIdleTimeValueGreater) 2620 if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
2590 return; 2621 return;
2591 2622
2592 IdleTimeQueryValue (NULL, &idle); 2623 IdleTimeQueryValue (NULL, &idle);