免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1741 | 回复: 1
打印 上一主题 下一主题

linux内核中断、异常 2................. [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-28 16:27 |只看该作者 |倒序浏览
linux内核中断、异常 2.................









异常返回

当执行异常处理的C函数终止时,程序执行一条jmp指令以跳转到ret_from_exception函数(上面的error_code汇编函数)


view plaincopy to clipboardprint?
  1. 01.ret_from_exception:  
  2. 02.    preempt_stop(CLBR_ANY)  
  3. 03.ret_from_intr:  
  4. 04.    GET_THREAD_INFO(%ebp)  
  5. 05.check_userspace:  
  6. 06.    movl PT_EFLAGS(%esp), %eax  # mix EFLAGS and CS  
  7. 07.    movb PT_CS(%esp), %al  
  8. 08.    andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax  
  9. 09.    cmpl $USER_RPL, %eax  
  10. 10.    /*当被中断的程序在中断发生运行时在内核态*/  
  11. 11.    jb resume_kernel        # not returning to v8086 or userspace  
  12. 12.    /*在用户空间时*/  
  13. 13.ENTRY(resume_userspace)  
  14. 14.    LOCKDEP_SYS_EXIT  
  15. 15.    DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt  
  16. 16.                    # setting need_resched or sigpending   
  17. 17.                    # between sampling and the iret   
  18. 18.    TRACE_IRQS_OFF  
  19. 19.    movl TI_flags(%ebp), %ecx  
  20. 20.    andl $_TIF_WORK_MASK, %ecx  # is there any work to be done on  
  21. 21.                    # int/exception return?   
  22. 22.    jne work_pending  
  23. 23.    jmp restore_all  
  24. 24.END(ret_from_exception)  
  25. 25.  
  26. 26.#ifdef CONFIG_PREEMPT   
  27. 27.ENTRY(resume_kernel)  
  28. 28.    DISABLE_INTERRUPTS(CLBR_ANY)  
  29. 29.    /*允许内核抢占时,执行need_resched*/  
  30. 30.    cmpl $0,TI_preempt_count(%ebp)  # non-zero preempt_count ?  
  31. 31.    /*不等于0,被中断的程序重新开始执行*/  
  32. 32.    jnz restore_all  
  33. 33.need_resched:  
  34. 34.    movl TI_flags(%ebp), %ecx   # need_resched set ?  
  35. 35.    testb $_TIF_NEED_RESCHED, %cl  
  36. 36.    jz restore_all  
  37. 37.    testl $X86_EFLAGS_IF,PT_EFLAGS(%esp)    # interrupts off (exception path) ?  
  38. 38.    jz restore_all  
  39. 39.    call preempt_schedule_irq  
  40. 40.    jmp need_resched  
  41. 41.END(resume_kernel)  
  42. 42.#endif   
  43. 43.    CFI_ENDPROC  
  44. ret_from_exception:
  45.         preempt_stop(CLBR_ANY)
  46. ret_from_intr:
  47.         GET_THREAD_INFO(%ebp)
  48. check_userspace:
  49.         movl PT_EFLAGS(%esp), %eax        # mix EFLAGS and CS
  50.         movb PT_CS(%esp), %al
  51.         andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
  52.         cmpl $USER_RPL, %eax
  53.         /*当被中断的程序在中断发生运行时在内核态*/
  54.         jb resume_kernel                # not returning to v8086 or userspace
  55.         /*在用户空间时*/
  56. ENTRY(resume_userspace)
  57.         LOCKDEP_SYS_EXIT
  58.         DISABLE_INTERRUPTS(CLBR_ANY)        # make sure we don't miss an interrupt
  59.                                         # setting need_resched or sigpending
  60.                                         # between sampling and the iret
  61.         TRACE_IRQS_OFF
  62.         movl TI_flags(%ebp), %ecx
  63.         andl $_TIF_WORK_MASK, %ecx        # is there any work to be done on
  64.                                         # int/exception return?
  65.         jne work_pending
  66.         jmp restore_all
  67. END(ret_from_exception)

  68. #ifdef CONFIG_PREEMPT
  69. ENTRY(resume_kernel)
  70.         DISABLE_INTERRUPTS(CLBR_ANY)
  71.         /*允许内核抢占时,执行need_resched*/
  72.         cmpl $0,TI_preempt_count(%ebp)        # non-zero preempt_count ?
  73.         /*不等于0,被中断的程序重新开始执行*/
  74.         jnz restore_all
  75. need_resched:
  76.         movl TI_flags(%ebp), %ecx        # need_resched set ?
  77.         testb $_TIF_NEED_RESCHED, %cl
  78.         jz restore_all
  79.         testl $X86_EFLAGS_IF,PT_EFLAGS(%esp)        # interrupts off (exception path) ?
  80.         jz restore_all
  81.         call preempt_schedule_irq
  82.         jmp need_resched
  83. END(resume_kernel)
  84. #endif
  85.         CFI_ENDPROC
复制代码
中断请求初始化

对于每一个外设,要么以静态(声明为 static 类型的全局变量)或动态(调用request_irq 函数)的方式向 Linux 内核注册中断处理程序。不管以何种方式注册,都会声明或分配一块irqaction 结构(其中handler 指向中断服务程序),然后调用setup_irq() 函数,将irq_desc_t 和irqaction 联系起来。irq_desc[]数组中每一项对应一个中断向量,每一个中断向量为一个irq_desc类型的变量,该变量中有个action指针,指向irqaction链表的首地址。也就是说多个中断服务(irqaction)可以共享一个中断向量,这些中断服务以链表的方式依次链入,当中断到来时,同一中断向量中的所有中断服务函数都会依次执行一遍。request_irq函数主要是实例化一个irqaction结构,这里直接看setup_irq函数。

view plaincopy to clipboardprint?
  1. 01./*
  2. 02. * Internal function to register an irqaction - typically used to
  3. 03. * allocate special interrupts that are part of the architecture.
  4. 04. */  
  5. 05. /*将中断服务链入irq_desc[irq]->action中*/  
  6. 06.static int  
  7. 07.__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)  
  8. 08.{  
  9. 09.    struct irqaction *old, **old_ptr;  
  10. 10.    const char *old_name = NULL;  
  11. 11.    unsigned long flags;  
  12. 12.    int nested, shared = 0;  
  13. 13.    int ret;  
  14. 14.  
  15. 15.    if (!desc)  
  16. 16.        return -EINVAL;  
  17. 17.  
  18. 18.    if (desc->chip == &no_irq_chip)  
  19. 19.        return -ENOSYS;  
  20. 20.    /*
  21. 21.     * Some drivers like serial.c use request_irq() heavily,
  22. 22.     * so we have to be careful not to interfere with a
  23. 23.     * running system.
  24. 24.     */  
  25. 25.    if (new->flags & IRQF_SAMPLE_RANDOM) {  
  26. 26.        /*
  27. 27.         * This function might sleep, we want to call it first,
  28. 28.         * outside of the atomic block.
  29. 29.         * Yes, this might clear the entropy pool if the wrong
  30. 30.         * driver is attempted to be loaded, without actually
  31. 31.         * installing a new handler, but is this really a problem,
  32. 32.         * only the sysadmin is able to do this.
  33. 33.         */  
  34. 34.        rand_initialize_irq(irq);  
  35. 35.    }  
  36. 36.  
  37. 37.    /* Oneshot interrupts are not allowed with shared */  
  38. 38.    if ((new->flags & IRQF_ONESHOT) && (new->flags & IRQF_SHARED))  
  39. 39.        return -EINVAL;  
  40. 40.  
  41. 41.    /*
  42. 42.     * Check whether the interrupt nests into another interrupt
  43. 43.     * thread.
  44. 44.     */  
  45. 45.     /*如果嵌套在另一个中断线程中*/  
  46. 46.    nested = desc->status & IRQ_NESTED_THREAD;  
  47. 47.    if (nested) {  
  48. 48.        if (!new->thread_fn)  
  49. 49.            return -EINVAL;  
  50. 50.        /*
  51. 51.         * Replace the primary handler which was provided from
  52. 52.         * the driver for non nested interrupt handling by the
  53. 53.         * dummy function which warns when called.
  54. 54.         */  
  55. 55.        new->handler = irq_nested_primary_handler;  
  56. 56.    }  
  57. 57.  
  58. 58.    /*
  59. 59.     * Create a handler thread when a thread function is supplied
  60. 60.     * and the interrupt does not nest into another interrupt
  61. 61.     * thread.
  62. 62.     *//*如果提供了中断线程*/  
  63. 63.    if (new->thread_fn && !nested) {  
  64. 64.        struct task_struct *t;  
  65. 65.        /*创建内核中断线程*/  
  66. 66.        t = kthread_create(irq_thread, new, "irq/%d-%s", irq,  
  67. 67.                   new->name);  
  68. 68.        if (IS_ERR(t))  
  69. 69.            return PTR_ERR(t);  
  70. 70.        /*
  71. 71.         * We keep the reference to the task struct even if
  72. 72.         * the thread dies to avoid that the interrupt code
  73. 73.         * references an already freed task_struct.
  74. 74.         *//*增加使用计数*/  
  75. 75.        get_task_struct(t);  
  76. 76.        new->thread = t;  
  77. 77.    }  
  78. 78.  
  79. 79.    /*
  80. 80.     * The following block of code has to be executed atomically
  81. 81.     */  
  82. 82.    spin_lock_irqsave(&desc->lock, flags);  
  83. 83.    old_ptr = &desc->action;/*保存action链表头*/  
  84. 84.    old = *old_ptr;  
  85. 85.    if (old) {/*如果链表不为空,也就是说该中断号对应的有中断服务函数*/  
  86. 86.        /*
  87. 87.         * Can't share interrupts unless both agree to and are
  88. 88.         * the same type (level, edge, polarity). So both flag
  89. 89.         * fields must have IRQF_SHARED set and the bits which
  90. 90.         * set the trigger type must match.
  91. 91.         */  
  92. 92.        if (!((old->flags & new->flags) & IRQF_SHARED) ||  
  93. 93.            ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) {  
  94. 94.            old_name = old->name;  
  95. 95.            goto mismatch;  
  96. 96.        }  
  97. 97.  
  98. 98.#if defined(CONFIG_IRQ_PER_CPU)   
  99. 99.        /* All handlers must agree on per-cpuness */  
  100. 100.        if ((old->flags & IRQF_PERCPU) !=  
  101. 101.            (new->flags & IRQF_PERCPU))  
  102. 102.            goto mismatch;  
  103. 103.#endif   
  104. 104.  
  105. 105.        /* add new interrupt at end of irq queue */  
  106. 106.        do {/*这一步是遍历到链表的最后一个
  107. 107.            old->next=NULL为止*/  
  108. 108.            old_ptr = &old->next;  
  109. 109.            old = *old_ptr;  
  110. 110.        } while (old);  
  111. 111.        shared = 1;/*共享*/  
  112. 112.    }  
  113. 113.  
  114. 114.    if (!shared) {  
  115. 115.        /*设置irq_desc[irq]结构中chip成员的还没设置的指针
  116. 116.        ,让它们指向一些默认函数*/  
  117. 117.        irq_chip_set_defaults(desc->chip);  
  118. 118.  
  119. 119.        init_waitqueue_head(&desc->wait_for_threads);  
  120. 120.  
  121. 121.        /* Setup the type (level, edge polarity) if configured: */  
  122. 122.        /*设置触发方式*/  
  123. 123.        if (new->flags & IRQF_TRIGGER_MASK) {  
  124. 124.            ret = __irq_set_trigger(desc, irq,  
  125. 125.                    new->flags & IRQF_TRIGGER_MASK);  
  126. 126.  
  127. 127.            if (ret)  
  128. 128.                goto out_thread;  
  129. 129.        } else  
  130. 130.            compat_irq_chip_set_default_handler(desc);  
  131. 131.#if defined(CONFIG_IRQ_PER_CPU)   
  132. 132.        if (new->flags & IRQF_PERCPU)  
  133. 133.            desc->status |= IRQ_PER_CPU;  
  134. 134.#endif   
  135. 135.  
  136. 136.        desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_ONESHOT |  
  137. 137.                  IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);  
  138. 138.  
  139. 139.        if (new->flags & IRQF_ONESHOT)  
  140. 140.            desc->status |= IRQ_ONESHOT;  
  141. 141.  
  142. 142.        if (!(desc->status & IRQ_NOAUTOEN)) {  
  143. 143.            desc->depth = 0;  
  144. 144.            desc->status &= ~IRQ_DISABLED;  
  145. 145.            desc->chip->startup(irq);  
  146. 146.        } else  
  147. 147.            /* Undo nested disables: */  
  148. 148.            desc->depth = 1;  
  149. 149.  
  150. 150.        /* Exclude IRQ from balancing if requested */  
  151. 151.        if (new->flags & IRQF_NOBALANCING)  
  152. 152.            desc->status |= IRQ_NO_BALANCING;  
  153. 153.  
  154. 154.        /* Set default affinity mask once everything is setup */  
  155. 155.        setup_affinity(irq, desc);  
  156. 156.  
  157. 157.    } else if ((new->flags & IRQF_TRIGGER_MASK)  
  158. 158.            && (new->flags & IRQF_TRIGGER_MASK)  
  159. 159.                != (desc->status & IRQ_TYPE_SENSE_MASK)) {  
  160. 160.        /* hope the handler works with the actual trigger mode... */  
  161. 161.        pr_warning("IRQ %d uses trigger mode %d; requested %d\n",  
  162. 162.                irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK),  
  163. 163.                (int)(new->flags & IRQF_TRIGGER_MASK));  
  164. 164.    }  
  165. 165.  
  166. 166.    new->irq = irq;/*将new的irq设置为irq*/  
  167. 167.    *old_ptr = new;/*将new链入链表中,这个从上面可以看到*/  
  168. 168.  
  169. 169.    /* Reset broken irq detection when installing new handler */  
  170. 170.    desc->irq_count = 0;  
  171. 171.    desc->irqs_unhandled = 0;  
  172. 172.  
  173. 173.    /*
  174. 174.     * Check whether we disabled the irq via the spurious handler
  175. 175.     * before. Reenable it and give it another chance.
  176. 176.     */  
  177. 177.    if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {  
  178. 178.        desc->status &= ~IRQ_SPURIOUS_DISABLED;  
  179. 179.        __enable_irq(desc, irq, false);/*启用中断*/  
  180. 180.    }  
  181. 181.  
  182. 182.    spin_unlock_irqrestore(&desc->lock, flags);  
  183. 183.  
  184. 184.    /*
  185. 185.     * Strictly no need to wake it up, but hung_task complains
  186. 186.     * when no hard interrupt wakes the thread up.
  187. 187.     */  
  188. 188.    if (new->thread)  
  189. 189.        wake_up_process(new->thread);  
  190. 190.    /*下面为注册proc文件系统对应的项*/  
  191. 191.    register_irq_proc(irq, desc);  
  192. 192.    new->dir = NULL;  
  193. 193.    register_handler_proc(irq, new);  
  194. 194.  
  195. 195.    return 0;  
  196. 196.  
  197. 197.mismatch:  
  198. 198.#ifdef CONFIG_DEBUG_SHIRQ   
  199. 199.    if (!(new->flags & IRQF_PROBE_SHARED)) {  
  200. 200.        printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);  
  201. 201.        if (old_name)  
  202. 202.            printk(KERN_ERR "current handler: %s\n", old_name);  
  203. 203.        dump_stack();  
  204. 204.    }  
  205. 205.#endif   
  206. 206.    ret = -EBUSY;  
  207. 207.  
  208. 208.out_thread:  
  209. 209.    spin_unlock_irqrestore(&desc->lock, flags);  
  210. 210.    if (new->thread) {  
  211. 211.        struct task_struct *t = new->thread;  
  212. 212.  
  213. 213.        new->thread = NULL;  
  214. 214.        if (likely(!test_bit(IRQTF_DIED, &new->thread_flags)))  
  215. 215.            kthread_stop(t);  
  216. 216.        put_task_struct(t);  
  217. 217.    }  
  218. 218.    return ret;  
  219. 219.}  
  220. /*
  221. * Internal function to register an irqaction - typically used to
  222. * allocate special interrupts that are part of the architecture.
  223. */
  224. /*将中断服务链入irq_desc[irq]->action中*/
  225. static int
  226. __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
  227. {
  228.         struct irqaction *old, **old_ptr;
  229.         const char *old_name = NULL;
  230.         unsigned long flags;
  231.         int nested, shared = 0;
  232.         int ret;

  233.         if (!desc)
  234.                 return -EINVAL;

  235.         if (desc->chip == &no_irq_chip)
  236.                 return -ENOSYS;
  237.         /*
  238.          * Some drivers like serial.c use request_irq() heavily,
  239.          * so we have to be careful not to interfere with a
  240.          * running system.
  241.          */
  242.         if (new->flags & IRQF_SAMPLE_RANDOM) {
  243.                 /*
  244.                  * This function might sleep, we want to call it first,
  245.                  * outside of the atomic block.
  246.                  * Yes, this might clear the entropy pool if the wrong
  247.                  * driver is attempted to be loaded, without actually
  248.                  * installing a new handler, but is this really a problem,
  249.                  * only the sysadmin is able to do this.
  250.                  */
  251.                 rand_initialize_irq(irq);
  252.         }

  253.         /* Oneshot interrupts are not allowed with shared */
  254.         if ((new->flags & IRQF_ONESHOT) && (new->flags & IRQF_SHARED))
  255.                 return -EINVAL;

  256.         /*
  257.          * Check whether the interrupt nests into another interrupt
  258.          * thread.
  259.          */
  260.          /*如果嵌套在另一个中断线程中*/
  261.         nested = desc->status & IRQ_NESTED_THREAD;
  262.         if (nested) {
  263.                 if (!new->thread_fn)
  264.                         return -EINVAL;
  265.                 /*
  266.                  * Replace the primary handler which was provided from
  267.                  * the driver for non nested interrupt handling by the
  268.                  * dummy function which warns when called.
  269.                  */
  270.                 new->handler = irq_nested_primary_handler;
  271.         }

  272.         /*
  273.          * Create a handler thread when a thread function is supplied
  274.          * and the interrupt does not nest into another interrupt
  275.          * thread.
  276.          *//*如果提供了中断线程*/
  277.         if (new->thread_fn && !nested) {
  278.                 struct task_struct *t;
  279.                 /*创建内核中断线程*/
  280.                 t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
  281.                                    new->name);
  282.                 if (IS_ERR(t))
  283.                         return PTR_ERR(t);
  284.                 /*
  285.                  * We keep the reference to the task struct even if
  286.                  * the thread dies to avoid that the interrupt code
  287.                  * references an already freed task_struct.
  288.                  *//*增加使用计数*/
  289.                 get_task_struct(t);
  290.                 new->thread = t;
  291.         }

  292.         /*
  293.          * The following block of code has to be executed atomically
  294.          */
  295.         spin_lock_irqsave(&desc->lock, flags);
  296.         old_ptr = &desc->action;/*保存action链表头*/
  297.         old = *old_ptr;
  298.         if (old) {/*如果链表不为空,也就是说该中断号对应的有中断服务函数*/
  299.                 /*
  300.                  * Can't share interrupts unless both agree to and are
  301.                  * the same type (level, edge, polarity). So both flag
  302.                  * fields must have IRQF_SHARED set and the bits which
  303.                  * set the trigger type must match.
  304.                  */
  305.                 if (!((old->flags & new->flags) & IRQF_SHARED) ||
  306.                     ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) {
  307.                         old_name = old->name;
  308.                         goto mismatch;
  309.                 }

  310. #if defined(CONFIG_IRQ_PER_CPU)
  311.                 /* All handlers must agree on per-cpuness */
  312.                 if ((old->flags & IRQF_PERCPU) !=
  313.                     (new->flags & IRQF_PERCPU))
  314.                         goto mismatch;
  315. #endif

  316.                 /* add new interrupt at end of irq queue */
  317.                 do {/*这一步是遍历到链表的最后一个
  318.                         old->next=NULL为止*/
  319.                         old_ptr = &old->next;
  320.                         old = *old_ptr;
  321.                 } while (old);
  322.                 shared = 1;/*共享*/
  323.         }

  324.         if (!shared) {
  325.                 /*设置irq_desc[irq]结构中chip成员的还没设置的指针
  326.                 ,让它们指向一些默认函数*/
  327.                 irq_chip_set_defaults(desc->chip);

  328.                 init_waitqueue_head(&desc->wait_for_threads);

  329.                 /* Setup the type (level, edge polarity) if configured: */
  330.                 /*设置触发方式*/
  331.                 if (new->flags & IRQF_TRIGGER_MASK) {
  332.                         ret = __irq_set_trigger(desc, irq,
  333.                                         new->flags & IRQF_TRIGGER_MASK);

  334.                         if (ret)
  335.                                 goto out_thread;
  336.                 } else
  337.                         compat_irq_chip_set_default_handler(desc);
  338. #if defined(CONFIG_IRQ_PER_CPU)
  339.                 if (new->flags & IRQF_PERCPU)
  340.                         desc->status |= IRQ_PER_CPU;
  341. #endif

  342.                 desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_ONESHOT |
  343.                                   IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);

  344.                 if (new->flags & IRQF_ONESHOT)
  345.                         desc->status |= IRQ_ONESHOT;

  346.                 if (!(desc->status & IRQ_NOAUTOEN)) {
  347.                         desc->depth = 0;
  348.                         desc->status &= ~IRQ_DISABLED;
  349.                         desc->chip->startup(irq);
  350.                 } else
  351.                         /* Undo nested disables: */
  352.                         desc->depth = 1;

  353.                 /* Exclude IRQ from balancing if requested */
  354.                 if (new->flags & IRQF_NOBALANCING)
  355.                         desc->status |= IRQ_NO_BALANCING;

  356.                 /* Set default affinity mask once everything is setup */
  357.                 setup_affinity(irq, desc);

  358.         } else if ((new->flags & IRQF_TRIGGER_MASK)
  359.                         && (new->flags & IRQF_TRIGGER_MASK)
  360.                                 != (desc->status & IRQ_TYPE_SENSE_MASK)) {
  361.                 /* hope the handler works with the actual trigger mode... */
  362.                 pr_warning("IRQ %d uses trigger mode %d; requested %d\n",
  363.                                 irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK),
  364.                                 (int)(new->flags & IRQF_TRIGGER_MASK));
  365.         }

  366.         new->irq = irq;/*将new的irq设置为irq*/
  367.         *old_ptr = new;/*将new链入链表中,这个从上面可以看到*/

  368.         /* Reset broken irq detection when installing new handler */
  369.         desc->irq_count = 0;
  370.         desc->irqs_unhandled = 0;

  371.         /*
  372.          * Check whether we disabled the irq via the spurious handler
  373.          * before. Reenable it and give it another chance.
  374.          */
  375.         if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {
  376.                 desc->status &= ~IRQ_SPURIOUS_DISABLED;
  377.                 __enable_irq(desc, irq, false);/*启用中断*/
  378.         }

  379.         spin_unlock_irqrestore(&desc->lock, flags);

  380.         /*
  381.          * Strictly no need to wake it up, but hung_task complains
  382.          * when no hard interrupt wakes the thread up.
  383.          */
  384.         if (new->thread)
  385.                 wake_up_process(new->thread);
  386.         /*下面为注册proc文件系统对应的项*/
  387.         register_irq_proc(irq, desc);
  388.         new->dir = NULL;
  389.         register_handler_proc(irq, new);

  390.         return 0;

  391. mismatch:
  392. #ifdef CONFIG_DEBUG_SHIRQ
  393.         if (!(new->flags & IRQF_PROBE_SHARED)) {
  394.                 printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
  395.                 if (old_name)
  396.                         printk(KERN_ERR "current handler: %s\n", old_name);
  397.                 dump_stack();
  398.         }
  399. #endif
  400.         ret = -EBUSY;

  401. out_thread:
  402.         spin_unlock_irqrestore(&desc->lock, flags);
  403.         if (new->thread) {
  404.                 struct task_struct *t = new->thread;

  405.                 new->thread = NULL;
  406.                 if (likely(!test_bit(IRQTF_DIED, &new->thread_flags)))
  407.                         kthread_stop(t);
  408.                 put_task_struct(t);
  409.         }
  410.         return ret;
  411. }
复制代码
中断相应和服务



论坛徽章:
0
2 [报告]
发表于 2011-12-28 16:36 |只看该作者
楼主辛苦
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP