{"id":196,"date":"2018-05-17T08:45:23","date_gmt":"2018-05-17T08:45:23","guid":{"rendered":"http:\/\/www.luo666.com\/?p=196"},"modified":"2019-01-19T04:42:25","modified_gmt":"2019-01-19T04:42:25","slug":"linux-%e5%86%85%e6%a0%b8-schedule%e6%97%b6%e7%9a%84preemption-notify%e6%9c%ba%e5%88%b6","status":"publish","type":"post","link":"http:\/\/www.luo666.com\/?p=196","title":{"rendered":"Linux \u5185\u6838 schedule\u65f6\u7684preemption notify\u673a\u5236"},"content":{"rendered":"<div>\u5185\u6838\u8fdb\u884c\u8fdb\u7a0b\u5207\u6362\u65f6\uff0c\u5148\u8c03\u7528\u4e86__schedule\uff0c\u5728\u5173\u62a2\u5360\u540e\u8c03\u7528context_switch\uff1a<\/div>\n<div>\n<div>\n<pre class=\"lang:c decode:true \">static void __sched __schedule(void)\n{\n\u00a0\u00a0\u00a0\u00a0struct task_struct *prev, *next;\n\u00a0\u00a0\u00a0\u00a0unsigned long *switch_count;\n\u00a0\u00a0\u00a0\u00a0struct rq *rq;\n\u00a0\u00a0\u00a0\u00a0int cpu;\n\nneed_resched:\n\u00a0\u00a0\u00a0\u00a0preempt_disable();\n\u00a0\u00a0\u00a0\u00a0cpu = smp_processor_id();\n\u00a0\u00a0\u00a0\u00a0rq = cpu_rq(cpu);\n...\nraw_spin_lock_irq(&amp;rq-&gt;lock);\n...\n\ncontext_switch(rq, prev, next);\n\n...\n\nsched_preempt_enable_no_resched();<\/pre>\n<\/div>\n<\/div>\n<div>\n<pre class=\"lang:c decode:true\">static inline void\ncontext_switch(struct rq *rq, struct task_struct *prev,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0struct task_struct *next)\n{\n\u00a0\u00a0\u00a0\u00a0struct mm_struct *mm, *oldmm;\n\n\u00a0\u00a0\u00a0\u00a0prepare_task_switch(rq, prev, next);\n\n\u00a0\u00a0\u00a0\u00a0mm = next-&gt;mm;\n\u00a0\u00a0\u00a0\u00a0oldmm = prev-&gt;active_mm;\n\u2026\n\n\u00a0\u00a0 \u00a0finish_task_switch(this_rq(), prev);<\/pre>\n<\/div>\n<div><\/div>\n<div>prepare_task_switch\u91cc\u9762\u8c03\u7528fire_sched_out_preempt_notifiers\uff0c\u8fdb\u800c\u8c03\u7528prev\u8fdb\u7a0b\u6ce8\u518c\u7684sched_out\u64cd\u4f5c\uff0c<\/div>\n<div>\n<div>\n<pre class=\"lang:c decode:true\">static inline void\nprepare_task_switch(struct rq *rq, struct task_struct *prev,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0struct task_struct *next)\n{\n\u00a0\u00a0\u00a0\u00a0trace_sched_switch(prev, next);\n\u00a0\u00a0\u00a0\u00a0sched_info_switch(prev, next);\n\u00a0\u00a0\u00a0\u00a0perf_event_task_sched_out(prev, next);\n\u00a0\u00a0\u00a0\u00a0fire_sched_out_preempt_notifiers(prev, next);\n\u00a0\u00a0\u00a0\u00a0prepare_lock_switch(rq, next);\n\u00a0\u00a0\u00a0\u00a0prepare_arch_switch(next);\n}<\/pre>\n<\/div>\n<\/div>\n<div>\u8fd9\u91cc\u662f\u5206\u652f\uff1a\u5982\u679c\u662f\u65b0\u521b\u5efa\u7684\u8fdb\u7a0b\u88ab\u8c03\u5ea6\u4e86\uff0c\u8981\u8c03\u7528schedule_tail\uff1a<\/div>\n<div>\n<pre class=\"lang:c decode:true\">\/**\n* schedule_tail - first thing a freshly forked thread must call.\n* @prev: the thread we just switched away from.\n*\/\nasmlinkage void schedule_tail(struct task_struct *prev)\n\u00a0\u00a0\u00a0\u00a0__releases(rq-&gt;lock)\n{\n\u00a0\u00a0\u00a0\u00a0struct rq *rq = this_rq();\n\n\u00a0\u00a0\u00a0\u00a0finish_task_switch(rq, prev);\n\n\u00a0\u00a0\u00a0\u00a0\/*\n\u00a0\u00a0\u00a0\u00a0\u00a0* FIXME: do we need to worry about rq being invalidated by the\n\u00a0\u00a0\u00a0\u00a0\u00a0* task_switch?\n\u00a0\u00a0\u00a0\u00a0\u00a0*\/\n\u00a0\u00a0\u00a0\u00a0post_schedule(rq);\n\n#ifdef __ARCH_WANT_UNLOCKED_CTXSW\n\u00a0\u00a0\u00a0\u00a0\/* In this case, finish_task_switch does not reenable preemption *\/\n\u00a0\u00a0\u00a0\u00a0preempt_enable();\n#endif\n\u00a0\u00a0\u00a0\u00a0if (current-&gt;set_child_tid)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0put_user(task_pid_vnr(current), current-&gt;set_child_tid);\n}<\/pre>\n<\/div>\n<div><\/div>\n<div><b>\u56de\u5230\u4e3b\u9898\uff1afinish_task_switch<\/b>\u8fd9\u91cc\u4f1a\u8c03\u7528fire_sched_in_preempt_notifiers:<\/div>\n<div>\n<pre class=\"lang:c decode:true\">static void fire_sched_in_preempt_notifiers(struct task_struct *curr)\n{\n\u00a0\u00a0\u00a0\u00a0struct preempt_notifier *notifier;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0hlist_for_each_entry(notifier, &amp;curr-&gt;preempt_notifiers, link)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0notifier-&gt;ops-&gt;sched_in(notifier, raw_smp_processor_id());\n}<\/pre>\n<\/div>\n<div>preempt_notifiers\u5728\u54ea\u91cc\u6ce8\u518c\u7684\u5462\uff0c\u5bf9kvm\u6765\u8bf4\u662f\u8fd9\u91cc\uff1a<\/div>\n<div>\n<pre class=\"lang:c decode:true \">static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)\n{\n\u00a0\u00a0\u00a0\u00a0int r;\n\u00a0\u00a0\u00a0\u00a0struct kvm_vcpu *vcpu, *v;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0if (id &gt;= KVM_MAX_VCPUS)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return -EINVAL;\n\u00a0\n\u00a0\u00a0\u00a0\u00a0vcpu = kvm_arch_vcpu_create(kvm, id);\n\u00a0\u00a0\u00a0\u00a0if (IS_ERR(vcpu))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return PTR_ERR(vcpu);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0preempt_notifier_init(&amp;vcpu-&gt;preempt_notifier, &amp;kvm_preempt_ops);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0r = kvm_arch_vcpu_setup(vcpu);<\/pre>\n<p>kvm\u6a21\u5757\u52a0\u8f7d\u7684\u65f6\u5019vmx_init-&gt;kvm_init\u91cc\u9762\u521d\u59cb\u5316\u4e86kvm_preempt_ops<\/p>\n<\/div>\n<div>\n<pre class=\"lang:c decode:true\">\u00a0\u00a0\u00a0\u00a0kvm_preempt_ops.sched_in = kvm_sched_in;\n\u00a0\u00a0\u00a0\u00a0kvm_preempt_ops.sched_out = kvm_sched_out;<\/pre>\n<\/div>\n<div><b>\u6240\u4ee5kvm_sched_in\u548ckvm_sched_out\u88ab\u8c03\u7528\u65f6\u7684\u4e0a\u4e0b\u6587\u662f\u5173\u62a2\u5360\u7684<\/b><\/div>\n<p><audio style=\"display: none;\" controls=\"controls\"><\/audio><\/p>\n<p><audio style=\"display: none;\" controls=\"controls\"><\/audio><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5185\u6838\u8fdb\u884c\u8fdb\u7a0b\u5207\u6362\u65f6\uff0c\u5148\u8c03\u7528\u4e86__schedule\uff0c\u5728\u5173\u62a2\u5360\u540e\u8c03\u7528context_switch\uff1a static void __sched __schedule(void) { \u00a0\u00a0\u00a0\u00a0struct task_struct *prev, *next; \u00a0\u00a0\u00a0\u00a0unsigned long *switch_count; \u00a0\u00a0\u00a0\u00a0struct rq *rq; \u00a0\u00a0\u00a0\u00a0int cpu; need_resched: \u00a0\u00a0\u00a0\u00a0preempt_disable(); \u00a0\u00a0\u00a0\u00a0cpu = smp_processor_id(); \u00a0\u00a0\u00a0\u00a0rq = cpu_rq(cpu); &#8230; raw_spin_lock_irq(&amp;rq-&gt;lock); &#8230; context_switch(rq, prev, next); &#8230; sched_preempt_enable_no_resched(); static inline void context_switch(struct rq *rq, struct task_struct *prev, \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0struct task_struct *next) { \u00a0\u00a0\u00a0\u00a0struct mm_struct *mm, *oldmm; \u00a0\u00a0\u00a0\u00a0prepare_task_switch(rq, prev, next); \u00a0\u00a0\u00a0\u00a0mm &hellip; <a href=\"http:\/\/www.luo666.com\/?p=196\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Linux \u5185\u6838 schedule\u65f6\u7684preemption notify\u673a\u5236&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false,"jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[3],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p7Dhki-3a","jetpack-related-posts":[],"_links":{"self":[{"href":"http:\/\/www.luo666.com\/index.php?rest_route=\/wp\/v2\/posts\/196"}],"collection":[{"href":"http:\/\/www.luo666.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.luo666.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.luo666.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.luo666.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=196"}],"version-history":[{"count":3,"href":"http:\/\/www.luo666.com\/index.php?rest_route=\/wp\/v2\/posts\/196\/revisions"}],"predecessor-version":[{"id":200,"href":"http:\/\/www.luo666.com\/index.php?rest_route=\/wp\/v2\/posts\/196\/revisions\/200"}],"wp:attachment":[{"href":"http:\/\/www.luo666.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=196"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.luo666.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=196"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.luo666.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=196"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}