timer: add timer_mod_anticipate and timer_mod_anticipate_ns
These let a user anticipate the deadline of a timer, atomically with other sites that call the function. This helps avoiding complicated lock hierarchies. Reviewed-by: Alex Bligh <alex@alex.org.uk> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									0f809e5fbe
								
							
						
					
					
						commit
						add40e9777
					
				@ -544,6 +544,19 @@ void timer_del(QEMUTimer *ts);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void timer_mod_ns(QEMUTimer *ts, int64_t expire_time);
 | 
					void timer_mod_ns(QEMUTimer *ts, int64_t expire_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * timer_mod_anticipate_ns:
 | 
				
			||||||
 | 
					 * @ts: the timer
 | 
				
			||||||
 | 
					 * @expire_time: the expiry time in nanoseconds
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Modify a timer to expire at @expire_time or the current time,
 | 
				
			||||||
 | 
					 * whichever comes earlier.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function is thread-safe but the timer and its timer list must not be
 | 
				
			||||||
 | 
					 * freed while this function is running.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * timer_mod:
 | 
					 * timer_mod:
 | 
				
			||||||
 * @ts: the timer
 | 
					 * @ts: the timer
 | 
				
			||||||
@ -557,6 +570,19 @@ void timer_mod_ns(QEMUTimer *ts, int64_t expire_time);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void timer_mod(QEMUTimer *ts, int64_t expire_timer);
 | 
					void timer_mod(QEMUTimer *ts, int64_t expire_timer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * timer_mod_anticipate:
 | 
				
			||||||
 | 
					 * @ts: the timer
 | 
				
			||||||
 | 
					 * @expire_time: the expiry time in nanoseconds
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Modify a timer to expire at @expire_time or the current time, whichever
 | 
				
			||||||
 | 
					 * comes earlier, taking into account the scale associated with the timer.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function is thread-safe but the timer and its timer list must not be
 | 
				
			||||||
 | 
					 * freed while this function is running.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * timer_pending:
 | 
					 * timer_pending:
 | 
				
			||||||
 * @ts: the timer
 | 
					 * @ts: the timer
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										29
									
								
								qemu-timer.c
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								qemu-timer.c
									
									
									
									
									
								
							@ -410,11 +410,40 @@ void timer_mod_ns(QEMUTimer *ts, int64_t expire_time)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* modify the current timer so that it will be fired when current_time
 | 
				
			||||||
 | 
					   >= expire_time or the current deadline, whichever comes earlier.
 | 
				
			||||||
 | 
					   The corresponding callback will be called. */
 | 
				
			||||||
 | 
					void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QEMUTimerList *timer_list = ts->timer_list;
 | 
				
			||||||
 | 
					    bool rearm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_mutex_lock(&timer_list->active_timers_lock);
 | 
				
			||||||
 | 
					    if (ts->expire_time == -1 || ts->expire_time > expire_time) {
 | 
				
			||||||
 | 
					        if (ts->expire_time != -1) {
 | 
				
			||||||
 | 
					            timer_del_locked(timer_list, ts);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        rearm = timer_mod_ns_locked(timer_list, ts, expire_time);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        rearm = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    qemu_mutex_unlock(&timer_list->active_timers_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (rearm) {
 | 
				
			||||||
 | 
					        timerlist_rearm(timer_list);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void timer_mod(QEMUTimer *ts, int64_t expire_time)
 | 
					void timer_mod(QEMUTimer *ts, int64_t expire_time)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    timer_mod_ns(ts, expire_time * ts->scale);
 | 
					    timer_mod_ns(ts, expire_time * ts->scale);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    timer_mod_anticipate_ns(ts, expire_time * ts->scale);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool timer_pending(QEMUTimer *ts)
 | 
					bool timer_pending(QEMUTimer *ts)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return ts->expire_time >= 0;
 | 
					    return ts->expire_time >= 0;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user