⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intr.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * @file * This file is part of the Xenomai project. * * @note Copyright (C) 2005 Philippe Gerum <rpm@xenomai.org>  * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * \ingroup interrupt *//*! * \ingroup native * \defgroup interrupt Interrupt management services. * *@{*/#include <nucleus/pod.h>#include <nucleus/registry.h>#include <native/task.h>#include <native/intr.h>static DECLARE_XNQUEUE(__xeno_intr_q);int __native_intr_pkg_init (void){    return 0;}void __native_intr_pkg_cleanup (void){    xnholder_t *holder;    while ((holder = getheadq(&__xeno_intr_q)) != NULL)	rt_intr_delete(link2intr(holder));}#ifdef CONFIG_XENO_EXPORT_REGISTRYstatic int __intr_read_proc (char *page,			     char **start,			     off_t off,			     int count,			     int *eof,			     void *data){    RT_INTR *intr = (RT_INTR *)data;    char *p = page;    int len;#ifdef CONFIG_XENO_OPT_PERVASIVE    {    xnpholder_t *holder;    spl_t s;    xnlock_get_irqsave(&nklock,s);    p += sprintf(p,"hits=%lu, pending=%u, mode=0x%x\n",		 intr->intr_base.hits,		 intr->pending,		 intr->mode);    /* Pended interrupt -- dump waiters. */    holder = getheadpq(xnsynch_wait_queue(&intr->synch_base));    while (holder)	{	xnthread_t *sleeper = link2thread(holder,plink);	p += sprintf(p,"+%s\n",xnthread_name(sleeper));	holder = nextpq(xnsynch_wait_queue(&intr->synch_base),holder);	}    xnlock_put_irqrestore(&nklock,s);    }#else /* !CONFIG_XENO_OPT_PERVASIVE */    p += sprintf(p,"hits=%lu\n",intr->intr_base.hits);#endif /* CONFIG_XENO_OPT_PERVASIVE */    len = (p - page) - off;    if (len <= off + count) *eof = 1;    *start = page + off;    if(len > count) len = count;    if(len < 0) len = 0;    return len;}extern xnptree_t __native_ptree;static xnpnode_t __intr_pnode = {    .dir = NULL,    .type = "interrupts",    .entries = 0,    .read_proc = &__intr_read_proc,    .write_proc = NULL,    .root = &__native_ptree,};#elif defined(CONFIG_XENO_OPT_REGISTRY)static xnpnode_t __intr_pnode = {    .type = "interrupts"};#endif /* CONFIG_XENO_EXPORT_REGISTRY *//*!  * \fn int rt_intr_create (RT_INTR *intr,const char *name,unsigned irq,rt_isr_t isr,rt_iack_t iack,int mode) * \brief Create an interrupt object from kernel space. * * Initializes and associates an interrupt object with an IRQ line. In * kernel space, interrupts are immediately notified to a user-defined * handler or ISR (interrupt service routine). * * When an interrupt occurs on the given @a irq line, the ISR is fired * in order to deal with the hardware event. The interrupt service * code may call any non-suspensive Xenomai service. * * Upon receipt of an IRQ, the ISR is immediately called on behalf of * the interrupted stack context, the rescheduling procedure is * locked, and the interrupt source is masked at hardware level. The * status value returned by the ISR is then checked for the following * values: * * - RT_INTR_HANDLED indicates that the interrupt request has been fulfilled * by the ISR. * * - RT_INTR_NONE indicates the opposite to RT_INTR_HANDLED. The ISR must always * return this value when it determines that the interrupt request has not been * issued by the dedicated hardware device. * * In addition, one of the following bits may be set by the ISR : * * NOTE: use these bits with care and only when you do understand their effect * on the system. * The ISR is not encouraged to use these bits in case it shares the IRQ line * with other ISRs in the real-time domain. * * - RT_INTR_PROPAGATE tells Xenomai to require the real-time control * layer to forward the IRQ. For instance, this would cause the Adeos * control layer to propagate the interrupt down the interrupt * pipeline to other Adeos domains, such as Linux. This is the regular * way to share interrupts between Xenomai and the Linux kernel. * * - RT_INTR_NOENABLE asks Xenomai not to re-enable the IRQ line upon return * of the interrupt service routine. * * A count of interrupt receipts is tracked into the interrupt * descriptor, and reset to zero each time the interrupt object is * attached. Since this count could wrap around, it should be used as * an indication of interrupt activity only. * * @param intr The address of a interrupt object descriptor Xenomai will * use to store the object-specific data.  This descriptor must always * be valid while the object is active therefore it must be allocated * in permanent memory. * * @param name An ASCII string standing for the symbolic name of the * interrupt object. When non-NULL and non-empty, this string is copied * to a safe place into the descriptor, and passed to the registry package * if enabled for indexing the created interrupt objects. * * @param irq The hardware interrupt channel associated with the * interrupt object. This value is architecture-dependent. * * @param isr The address of a valid interrupt service routine in * kernel space. This handler will be called each time the * corresponding IRQ is delivered on behalf of an interrupt context. * A pointer to an internal information is passed to the routine which * can use it to retrieve the descriptor address of the associated * interrupt object through the I_DESC() macro. * * @param iack The address of an optional interrupt acknowledge * routine, aimed at replacing the default one. Only very specific * situations actually require to override the default setting for * this parameter, like having to acknowledge non-standard PIC * hardware. @a iack should return a non-zero value to indicate that * the interrupt has been properly acknowledged. If @a iack is NULL, * the default routine will be used instead. * * @param mode The interrupt object creation mode. The following flags can be * OR'ed into this bitmask, each of them affecting the new interrupt object: * * - I_SHARED enables IRQ-sharing with other interrupt objects. * * - I_EDGE is an additional flag need to be set together with I_SHARED * to enable IRQ-sharing of edge-triggered interrupts. * * @return 0 is returned upon success. Otherwise: * * - -ENOMEM is returned if the system fails to get enough dynamic * memory from the global real-time heap in order to register the * interrupt object. * * - -EBUSY is returned if the interrupt line is already in use by * another interrupt object. Only a single interrupt object can be * associated to any given interrupt line using rt_intr_create() at * any time. * * - -EEXIST is returned if @a irq is already associated to an * existing interrupt object. * * - -EPERM is returned if this service was called from an * asynchronous context. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * * Rescheduling: possible. * * @note The interrupt source associated to the interrupt descriptor * remains masked upon creation. rt_intr_enable() should be called for * the new interrupt object to unmask it. */int rt_intr_create (RT_INTR *intr,		    const char *name,		    unsigned irq,		    rt_isr_t isr,		    rt_iack_t iack,		    int mode){    int err;    spl_t s;    if (xnpod_asynch_p())	return -EPERM;    xnintr_init(&intr->intr_base,name,irq,isr,iack,mode);    xnobject_copy_name(intr->name,name);#if defined(__KERNEL__) && defined(CONFIG_XENO_OPT_PERVASIVE)    xnsynch_init(&intr->synch_base,XNSYNCH_PRIO);    intr->pending = 0;    intr->cpid = 0;    intr->mode = 0;#endif /* __KERNEL__ && CONFIG_XENO_OPT_PERVASIVE */    intr->magic = XENO_INTR_MAGIC;    intr->handle = 0;    /* i.e. (still) unregistered interrupt. */    inith(&intr->link);    xnlock_get_irqsave(&nklock,s);    appendq(&__xeno_intr_q,&intr->link);    xnlock_put_irqrestore(&nklock,s);    err = xnintr_attach(&intr->intr_base,intr);#ifdef CONFIG_XENO_OPT_REGISTRY    /* <!> Since xnregister_enter() may reschedule, only register       complete objects, so that the registry cannot return handles to       half-baked objects... */    if (!err)	err = xnregistry_enter(intr->name,intr,&intr->handle,&__intr_pnode);#endif /* CONFIG_XENO_OPT_REGISTRY */    if (err)	rt_intr_delete(intr);    return err;}/** * @fn int rt_intr_delete(RT_INTR *intr) * @brief Delete an interrupt object. * * Destroys an interrupt object.  An interrupt exists in the system * since rt_intr_create() has been called to create it, so this * service must be called in order to destroy it afterwards. * * Any user-space task which might be currently pending on the * interrupt object through the rt_intr_wait() service will be awaken * as a result of the deletion, and return with the -EIDRM status. * * @param intr The descriptor address of the affected interrupt object. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a intr is not a interrupt object * descriptor. * * - -EIDRM is returned if @a intr is a deleted interrupt object * descriptor. * * - -EPERM is returned if this service was called from an * asynchronous context. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task * * Rescheduling: possible. */int rt_intr_delete (RT_INTR *intr){    int err = 0, rc = XNSYNCH_DONE;    spl_t s;    if (xnpod_asynch_p())	return -EPERM;    xnlock_get_irqsave(&nklock,s);    intr = xeno_h2obj_validate(intr,XENO_INTR_MAGIC,RT_INTR);    if (!intr)        {        err = xeno_handle_error(intr,XENO_INTR_MAGIC,RT_INTR);        goto unlock_and_exit;        }        removeq(&__xeno_intr_q,&intr->link);#if defined(__KERNEL__) && defined(CONFIG_XENO_OPT_PERVASIVE)    rc = xnsynch_destroy(&intr->synch_base);#endif /* __KERNEL__ && CONFIG_XENO_OPT_PERVASIVE */    xnintr_detach(&intr->intr_base);#ifdef CONFIG_XENO_OPT_REGISTRY    if (intr->handle)        xnregistry_remove(intr->handle);#endif /* CONFIG_XENO_OPT_REGISTRY */    xnintr_destroy(&intr->intr_base);    xeno_mark_deleted(intr);    if (rc == XNSYNCH_RESCHED)        /* Some task has been woken up as a result of the deletion:           reschedule now. */        xnpod_schedule(); unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return err;}/*!  * \fn int rt_intr_enable (RT_INTR *intr) * \brief Enable an interrupt object. * * Enables the hardware interrupt line associated with an interrupt * object. Over Adeos-based systems which mask and acknowledge IRQs * upon receipt, this operation is necessary to revalidate the * interrupt channel so that more interrupts from the same source can * be notified.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -