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
This commit is contained in:
		
							parent
							
								
									1a99110f0c
								
							
						
					
					
						commit
						1f4fb0225b
					
				
							
								
								
									
										51
									
								
								Xext/sync.c
								
								
								
								
							
							
						
						
									
										51
									
								
								Xext/sync.c
								
								
								
								
							|  | @ -2281,7 +2281,7 @@ SyncInitServerTime(void) | |||
|  * IDLETIME implementation | ||||
|  */ | ||||
| 
 | ||||
| static pointer IdleTimeCounter; | ||||
| static SyncCounter *IdleTimeCounter; | ||||
| static XSyncValue *pIdleTimeValueLess; | ||||
| static XSyncValue *pIdleTimeValueGreater; | ||||
| 
 | ||||
|  | @ -2293,38 +2293,69 @@ IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) | |||
| } | ||||
| 
 | ||||
| static void | ||||
| IdleTimeBlockHandler (pointer env, | ||||
|                       struct timeval **wt, | ||||
|                       pointer LastSelectMask) | ||||
| IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) | ||||
| { | ||||
|     XSyncValue idle; | ||||
|     XSyncValue idle, old_idle; | ||||
|     SyncTriggerList *list = IdleTimeCounter->pTriglist; | ||||
|     SyncTrigger *trig; | ||||
| 
 | ||||
|     if (!pIdleTimeValueLess && !pIdleTimeValueGreater) | ||||
| 	return; | ||||
| 
 | ||||
|     old_idle = IdleTimeCounter->value; | ||||
|     IdleTimeQueryValue (NULL, &idle); | ||||
|     IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ | ||||
| 
 | ||||
|     if (pIdleTimeValueLess && | ||||
|         XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) | ||||
|     { | ||||
| 	AdjustWaitForDelay (wt, 0); | ||||
| 	/*
 | ||||
| 	 * We've been idle for less than the threshold value, and someone | ||||
| 	 * wants to know about that, but now we need to know whether they | ||||
| 	 * want level or edge trigger.  Check the trigger list against the | ||||
| 	 * current idle time, and if any succeed, bomb out of select() | ||||
| 	 * immediately so we can reschedule. | ||||
| 	 */ | ||||
| 
 | ||||
| 	for (list = IdleTimeCounter->pTriglist; list; list = list->next) { | ||||
| 	    trig = list->pTrigger; | ||||
| 	    if (trig->CheckTrigger(trig, old_idle)) { | ||||
| 		AdjustWaitForDelay(wt, 0); | ||||
| 		break; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|     else if (pIdleTimeValueGreater) | ||||
|     { | ||||
| 	unsigned long timeout = 0; | ||||
| 	/*
 | ||||
| 	 * There's a threshold in the positive direction.  If we've been | ||||
| 	 * idle less than it, schedule a wakeup for sometime in the future. | ||||
| 	 * If we've been idle more than it, and someone wants to know about | ||||
| 	 * that level-triggered, schedule an immediate wakeup. | ||||
| 	 */ | ||||
| 	unsigned long timeout = -1; | ||||
| 
 | ||||
| 	if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) | ||||
| 	{ | ||||
| 	if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { | ||||
| 	    XSyncValue value; | ||||
| 	    Bool overflow; | ||||
| 
 | ||||
| 	    XSyncValueSubtract (&value, *pIdleTimeValueGreater, | ||||
| 	                        idle, &overflow); | ||||
| 	    timeout = XSyncValueLow32 (value); | ||||
| 	    timeout = min(timeout, XSyncValueLow32 (value)); | ||||
| 	} else { | ||||
| 	    for (list = IdleTimeCounter->pTriglist; list; list = list->next) { | ||||
| 		trig = list->pTrigger; | ||||
| 		if (trig->CheckTrigger(trig, old_idle)) { | ||||
| 		    timeout = min(timeout, 0); | ||||
| 		    break; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
| 
 | ||||
| 	AdjustWaitForDelay (wt, timeout); | ||||
|     } | ||||
| 
 | ||||
|     IdleTimeCounter->value = old_idle; /* pop */ | ||||
| } | ||||
| 
 | ||||
| static void | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue