Messages in this thread Patch in this message | | | Date | Fri, 3 Jul 2015 17:16:42 +0200 | From | Peter Zijlstra <> | Subject | Re: [PATCH] sched,kvm: Fix KVM preempt_notifier usage |
| |
On Fri, Jul 03, 2015 at 03:17:13PM +0200, Peter Zijlstra wrote: > But, could we rework the code so that you register the preempt notifier > when creating the vcpu thread and leave it installed forevermore?
OK, it looks like there is no fixed relation between a thread and a vcpu :/
Would something like the below (on top of all the others) work for you?
--- include/linux/preempt.h | 2 ++ kernel/sched/core.c | 18 +++++++++++++++--- virt/kvm/kvm_main.c | 7 +++++-- 3 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/include/linux/preempt.h b/include/linux/preempt.h index 0f1534acaf60..84991f185173 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -293,6 +293,8 @@ struct preempt_notifier { struct preempt_ops *ops; }; +void preempt_notifier_inc(void); +void preempt_notifier_dec(void); void preempt_notifier_register(struct preempt_notifier *notifier); void preempt_notifier_unregister(struct preempt_notifier *notifier); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 6169c167ac98..5ddbcb720fc6 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2320,13 +2320,27 @@ void wake_up_new_task(struct task_struct *p) static struct static_key preempt_notifier_key = STATIC_KEY_INIT_FALSE; +void preempt_notifier_inc(void) +{ + static_key_slow_inc(&preempt_notifier_key); +} +EXPORT_SYMBOL_GPL(preempt_notifier_inc); + +void preempt_notifier_dec(void) +{ + static_key_slow_dec(&preempt_notifier_key); +} +EXPORT_SYMBOL_GPL(preempt_notifier_dec); + /** * preempt_notifier_register - tell me when current is being preempted & rescheduled * @notifier: notifier struct to register */ void preempt_notifier_register(struct preempt_notifier *notifier) { - static_key_slow_inc(&preempt_notifier_key); + if (!static_key_false(&preempt_notifier_key)) + WARN(1, "registering preempt_notifier while notifiers disabled\n"); + /* * Avoid preemption while changing the preempt notifier list. */ @@ -2350,8 +2364,6 @@ void preempt_notifier_unregister(struct preempt_notifier *notifier) preempt_disable(); hlist_del(¬ifier->link); preempt_enable(); - - static_key_slow_dec(&preempt_notifier_key); } EXPORT_SYMBOL_GPL(preempt_notifier_unregister); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index d7aafa0458a0..8136be28d76c 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -128,9 +128,9 @@ int vcpu_load(struct kvm_vcpu *vcpu) if (mutex_lock_killable(&vcpu->mutex)) return -EINTR; - preempt_notifier_register(&vcpu->preempt_notifier); cpu = get_cpu(); + preempt_notifier_register(&vcpu->preempt_notifier); kvm_arch_vcpu_load(vcpu, cpu); put_cpu(); return 0; @@ -140,8 +140,8 @@ void vcpu_put(struct kvm_vcpu *vcpu) { preempt_disable(); kvm_arch_vcpu_put(vcpu); - preempt_enable(); preempt_notifier_unregister(&vcpu->preempt_notifier); + preempt_enable(); mutex_unlock(&vcpu->mutex); } @@ -513,6 +513,8 @@ static struct kvm *kvm_create_vm(unsigned long type) list_add(&kvm->vm_list, &vm_list); spin_unlock(&kvm_lock); + preempt_notifier_inc(); + return kvm; out_err: @@ -612,6 +614,7 @@ static void kvm_destroy_vm(struct kvm *kvm) cleanup_srcu_struct(&kvm->irq_srcu); cleanup_srcu_struct(&kvm->srcu); kvm_arch_free_vm(kvm); + preempt_notifier_dec(); hardware_disable_all(); mmdrop(mm); }
| |