mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Add a new timer operation kill_timer(). Effectively the
'opposite' of init_timer(), it marks the end of a timer's lifetime. After this call the timer will not be pending, its callback handler will not be running, and future calls to set_timer() will silently fail. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
c5c75c2926
commit
cc00657854
5 files changed
+80
-45
No files matched your search
+3
-5
@@ -105,13 +105,11 @@ void vmx_relinquish_resources(struct vcpu *v)
|
||||
destroy_vmcs(&v->arch.arch_vmx);
|
||||
free_monitor_pagetable(v);
|
||||
vpit = &v->domain->arch.vmx_platform.vmx_pit;
|
||||
if ( active_timer(&(vpit->pit_timer)) )
|
||||
stop_timer(&vpit->pit_timer);
|
||||
if ( active_timer(&v->arch.arch_vmx.hlt_timer) )
|
||||
stop_timer(&v->arch.arch_vmx.hlt_timer);
|
||||
kill_timer(&vpit->pit_timer);
|
||||
kill_timer(&v->arch.arch_vmx.hlt_timer);
|
||||
if ( vmx_apic_support(v->domain) && (VLAPIC(v) != NULL) )
|
||||
{
|
||||
stop_timer(&VLAPIC(v)->vlapic_timer);
|
||||
kill_timer(&VLAPIC(v)->vlapic_timer);
|
||||
xfree(VLAPIC(v));
|
||||
}
|
||||
}
|
||||
|
||||
+37
-29
@@ -45,9 +45,9 @@ struct bvt_dom_info
|
||||
limits*/
|
||||
s32 warp_value; /* virtual time warp */
|
||||
s_time_t warpl; /* warp limit */
|
||||
struct timer warp_timer; /* deals with warpl */
|
||||
struct timer warp_timer; /* deals with warpl */
|
||||
s_time_t warpu; /* unwarp time requirement */
|
||||
struct timer unwarp_timer; /* deals with warpu */
|
||||
struct timer unwarp_timer; /* deals with warpu */
|
||||
|
||||
struct bvt_vcpu_info vcpu_inf[MAX_VIRT_CPUS];
|
||||
};
|
||||
@@ -168,6 +168,7 @@ static inline u32 calc_evt(struct vcpu *d, u32 avt)
|
||||
static int bvt_alloc_task(struct vcpu *v)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
struct bvt_dom_info *inf;
|
||||
|
||||
if ( (d->sched_priv == NULL) )
|
||||
{
|
||||
@@ -176,32 +177,12 @@ static int bvt_alloc_task(struct vcpu *v)
|
||||
memset(d->sched_priv, 0, sizeof(struct bvt_dom_info));
|
||||
}
|
||||
|
||||
v->sched_priv = &BVT_INFO(d)->vcpu_inf[v->vcpu_id];
|
||||
inf = BVT_INFO(d);
|
||||
|
||||
BVT_INFO(d)->vcpu_inf[v->vcpu_id].inf = BVT_INFO(d);
|
||||
BVT_INFO(d)->vcpu_inf[v->vcpu_id].vcpu = v;
|
||||
v->sched_priv = &inf->vcpu_inf[v->vcpu_id];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add and remove a domain
|
||||
*/
|
||||
static void bvt_add_task(struct vcpu *v)
|
||||
{
|
||||
struct bvt_dom_info *inf = BVT_INFO(v->domain);
|
||||
struct bvt_vcpu_info *einf = EBVT_INFO(v);
|
||||
ASSERT(inf != NULL);
|
||||
ASSERT(v != NULL);
|
||||
|
||||
/* Allocate per-CPU context if this is the first domain to be added. */
|
||||
if ( CPU_INFO(v->processor) == NULL )
|
||||
{
|
||||
schedule_data[v->processor].sched_priv = xmalloc(struct bvt_cpu_info);
|
||||
BUG_ON(CPU_INFO(v->processor) == NULL);
|
||||
INIT_LIST_HEAD(RUNQUEUE(v->processor));
|
||||
CPU_SVT(v->processor) = 0;
|
||||
}
|
||||
inf->vcpu_inf[v->vcpu_id].inf = BVT_INFO(d);
|
||||
inf->vcpu_inf[v->vcpu_id].vcpu = v;
|
||||
|
||||
if ( v->vcpu_id == 0 )
|
||||
{
|
||||
@@ -218,7 +199,28 @@ static void bvt_add_task(struct vcpu *v)
|
||||
init_timer(&inf->unwarp_timer, unwarp_timer_fn, inf, v->processor);
|
||||
}
|
||||
|
||||
einf->vcpu = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add and remove a domain
|
||||
*/
|
||||
static void bvt_add_task(struct vcpu *v)
|
||||
{
|
||||
struct bvt_dom_info *inf = BVT_INFO(v->domain);
|
||||
struct bvt_vcpu_info *einf = EBVT_INFO(v);
|
||||
|
||||
ASSERT(inf != NULL);
|
||||
ASSERT(v != NULL);
|
||||
|
||||
/* Allocate per-CPU context if this is the first domain to be added. */
|
||||
if ( CPU_INFO(v->processor) == NULL )
|
||||
{
|
||||
schedule_data[v->processor].sched_priv = xmalloc(struct bvt_cpu_info);
|
||||
BUG_ON(CPU_INFO(v->processor) == NULL);
|
||||
INIT_LIST_HEAD(RUNQUEUE(v->processor));
|
||||
CPU_SVT(v->processor) = 0;
|
||||
}
|
||||
|
||||
if ( is_idle_vcpu(v) )
|
||||
{
|
||||
@@ -305,8 +307,14 @@ static int bvt_set_affinity(struct vcpu *v, cpumask_t *affinity)
|
||||
*/
|
||||
static void bvt_free_task(struct domain *d)
|
||||
{
|
||||
ASSERT(d->sched_priv != NULL);
|
||||
xfree(d->sched_priv);
|
||||
struct bvt_dom_info *inf = BVT_INFO(d);
|
||||
|
||||
ASSERT(inf != NULL);
|
||||
|
||||
kill_timer(&inf->warp_timer);
|
||||
kill_timer(&inf->unwarp_timer);
|
||||
|
||||
xfree(inf);
|
||||
}
|
||||
|
||||
/* Control the scheduler. */
|
||||
|
||||
@@ -156,7 +156,7 @@ void sched_add_domain(struct vcpu *v)
|
||||
|
||||
void sched_rem_domain(struct vcpu *v)
|
||||
{
|
||||
stop_timer(&v->timer);
|
||||
kill_timer(&v->timer);
|
||||
SCHED_OP(rem_task, v);
|
||||
TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id);
|
||||
}
|
||||
@@ -462,7 +462,7 @@ static void s_timer_fn(void *unused)
|
||||
/* Periodic tick timer: send timer event to current domain */
|
||||
static void t_timer_fn(void *unused)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
struct vcpu *v = current;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
schedule_data[cpu].tick++;
|
||||
|
||||
+29
-9
@@ -29,6 +29,7 @@
|
||||
struct timers {
|
||||
spinlock_t lock;
|
||||
struct timer **heap;
|
||||
struct timer *running;
|
||||
} __cacheline_aligned;
|
||||
|
||||
struct timers timers[NR_CPUS];
|
||||
@@ -167,11 +168,11 @@ void set_timer(struct timer *timer, s_time_t expires)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&timers[cpu].lock, flags);
|
||||
ASSERT(timer != NULL);
|
||||
if ( active_timer(timer) )
|
||||
__stop_timer(timer);
|
||||
timer->expires = expires;
|
||||
__add_timer(timer);
|
||||
if ( likely(!timer->killed) )
|
||||
__add_timer(timer);
|
||||
spin_unlock_irqrestore(&timers[cpu].lock, flags);
|
||||
}
|
||||
|
||||
@@ -182,13 +183,31 @@ void stop_timer(struct timer *timer)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&timers[cpu].lock, flags);
|
||||
ASSERT(timer != NULL);
|
||||
if ( active_timer(timer) )
|
||||
__stop_timer(timer);
|
||||
spin_unlock_irqrestore(&timers[cpu].lock, flags);
|
||||
}
|
||||
|
||||
|
||||
void kill_timer(struct timer *timer)
|
||||
{
|
||||
int cpu = timer->cpu;
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(timers[cpu].running == timer);
|
||||
|
||||
spin_lock_irqsave(&timers[cpu].lock, flags);
|
||||
if ( active_timer(timer) )
|
||||
__stop_timer(timer);
|
||||
timer->killed = 1;
|
||||
spin_unlock_irqrestore(&timers[cpu].lock, flags);
|
||||
|
||||
for_each_online_cpu ( cpu )
|
||||
while ( timers[cpu].running == timer )
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
|
||||
static void timer_softirq_action(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
@@ -208,19 +227,20 @@ static void timer_softirq_action(void)
|
||||
{
|
||||
remove_entry(heap, t);
|
||||
|
||||
timers[cpu].running = t;
|
||||
|
||||
fn = t->function;
|
||||
data = t->data;
|
||||
|
||||
if ( fn != NULL )
|
||||
{
|
||||
spin_unlock_irq(&timers[cpu].lock);
|
||||
(*fn)(data);
|
||||
spin_lock_irq(&timers[cpu].lock);
|
||||
}
|
||||
spin_unlock_irq(&timers[cpu].lock);
|
||||
(*fn)(data);
|
||||
spin_lock_irq(&timers[cpu].lock);
|
||||
|
||||
/* Heap may have grown while the lock was released. */
|
||||
heap = timers[cpu].heap;
|
||||
}
|
||||
|
||||
timers[cpu].running = NULL;
|
||||
}
|
||||
while ( !reprogram_timer(GET_HEAP_SIZE(heap) ? heap[1]->expires : 0) );
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ struct timer {
|
||||
void *data;
|
||||
/* Timer-heap offset. */
|
||||
unsigned int heap_offset;
|
||||
/* Has this timer been killed (cannot be activated)? */
|
||||
int killed;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -63,6 +65,13 @@ extern void set_timer(struct timer *timer, s_time_t expires);
|
||||
*/
|
||||
extern void stop_timer(struct timer *timer);
|
||||
|
||||
/*
|
||||
* Deactivate a timer and prevent it from being re-set (future calls to
|
||||
* set_timer will silently fail). When this function returns it is guaranteed
|
||||
* that the timer callback handler is not running on any CPU.
|
||||
*/
|
||||
extern void kill_timer(struct timer *timer);
|
||||
|
||||
/*
|
||||
* Initialisation. Must be called before any other timer function.
|
||||
*/
|
||||
|
||||