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

📄 event.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * @file * This file is part of the Xenomai project. * * @note Copyright (C) 2004 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 event *//*! * \ingroup native * \defgroup event Event flag group services. * * An event flag group is a synchronization object represented by a * long-word structure; every available bit in such word can be used * to map a user-defined event flag.  When a flag is set, the * associated event is said to have occurred. Xenomai tasks and interrupt * handlers can use event flags to signal the occurrence of events to * other tasks; those tasks can either wait for the events to occur in * a conjunctive manner (all awaited events must have occurred to wake * up), or in a disjunctive way (at least one of the awaited events * must have occurred to wake up). * *@{*/#include <nucleus/pod.h>#include <nucleus/registry.h>#include <native/task.h>#include <native/event.h>#ifdef CONFIG_XENO_EXPORT_REGISTRYstatic int __event_read_proc (char *page,			      char **start,			      off_t off,			      int count,			      int *eof,			      void *data){    RT_EVENT *event = (RT_EVENT *)data;    char *p = page;    int len;    spl_t s;    xnlock_get_irqsave(&nklock,s);    p += sprintf(p,"=0x%lx\n",event->value);    if (xnsynch_nsleepers(&event->synch_base) > 0)	{	xnpholder_t *holder;	/* Pended event -- dump waiters. */	holder = getheadpq(xnsynch_wait_queue(&event->synch_base));	while (holder)	    {	    xnthread_t *sleeper = link2thread(holder,plink);	    RT_TASK *task = thread2rtask(sleeper);	    const char *mode = (task->wait_args.event.mode & EV_ANY) ? "any" : "all";	    unsigned long mask = task->wait_args.event.mask;	    p += sprintf(p,"+%s (mask=0x%lx, %s)\n",xnthread_name(sleeper),mask,mode);	    holder = nextpq(xnsynch_wait_queue(&event->synch_base),holder);	    }	}    xnlock_put_irqrestore(&nklock,s);    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 __event_pnode = {    .dir = NULL,    .type = "events",    .entries = 0,    .read_proc = &__event_read_proc,    .write_proc = NULL,    .root = &__native_ptree,};#elif defined(CONFIG_XENO_OPT_REGISTRY)static xnpnode_t __event_pnode = {    .type = "events"};#endif /* CONFIG_XENO_EXPORT_REGISTRY *//** * @fn int rt_event_create(RT_EVENT *event,const char *name,unsigned long ivalue,int mode) * @brief Create an event group. * * Event groups provide for task synchronization by allowing a set of * flags (or "events") to be waited for and posted atomically. An * event group contains a mask of received events; any set of bits * from the event mask can be pended or posted in a single operation. * * Tasks can wait for a conjunctive (AND) or disjunctive (OR) set of * events to occur.  A task pending on an event group in conjunctive * mode is woken up as soon as all awaited events are set in the event * mask. A task pending on an event group in disjunctive mode is woken * up as soon as any awaited event is set in the event mask. * @param event The address of an event group descriptor Xenomai will * use to store the event-related data.  This descriptor must always * be valid while the group is active therefore it must be allocated * in permanent memory. * * @param name An ASCII string standing for the symbolic name of the * group. 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 event group. * * @param ivalue The initial value of the group's event mask. * * @param mode The event group creation mode. The following flags can * be OR'ed into this bitmask, each of them affecting the new group: * * - EV_FIFO makes tasks pend in FIFO order on the event group. * * - EV_PRIO makes tasks pend in priority order on the event group. * * @return 0 is returned upon success. Otherwise: * * - -EEXIST is returned if the @a name is already in use by some * registered object. * * - -EPERM is returned if this service was called from an * asynchronous context. * * - -ENOMEM is returned if the system fails to get enough dynamic * memory from the global real-time heap in order to register the * event group. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task * * Rescheduling: possible. */int rt_event_create (RT_EVENT *event,                     const char *name,                     unsigned long ivalue,                     int mode){    int err = 0;    if (xnpod_asynch_p())	return -EPERM;    xnsynch_init(&event->synch_base,mode & EV_PRIO);    event->value = ivalue;    event->handle = 0;  /* i.e. (still) unregistered event. */    event->magic = XENO_EVENT_MAGIC;    xnobject_copy_name(event->name,name);#if defined(__KERNEL__) && defined(CONFIG_XENO_OPT_PERVASIVE)    event->cpid = 0;#endif /* __KERNEL__ && CONFIG_XENO_OPT_PERVASIVE */#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 (name)        {	xnpnode_t *pnode = &__event_pnode;		if (!*name)	    {	    /* Since this is an anonymous object (empty name on entry)	       from user-space, it gets registered under an unique	       internal name but is not exported through /proc. */	    xnobject_create_name(event->name,sizeof(event->name),(void*)event);	    pnode = NULL;	    }	            err = xnregistry_enter(event->name,event,&event->handle,pnode);        if (err)            rt_event_delete(event);        }#endif /* CONFIG_XENO_OPT_REGISTRY */    return err;}/** * @fn int rt_event_delete(RT_EVENT *event) * @brief Delete an event group. * * Destroy an event group and release all the tasks currently pending * on it.  An event group exists in the system since rt_event_create() * has been called to create it, so this service must be called in * order to destroy it afterwards. * * @param event The descriptor address of the affected event group. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a event is not a event group descriptor. * * - -EIDRM is returned if @a event is a deleted event group 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_event_delete (RT_EVENT *event){    int err = 0, rc;    spl_t s;    if (xnpod_asynch_p())	return -EPERM;    xnlock_get_irqsave(&nklock,s);    event = xeno_h2obj_validate(event,XENO_EVENT_MAGIC,RT_EVENT);    if (!event)        {        err = xeno_handle_error(event,XENO_EVENT_MAGIC,RT_EVENT);        goto unlock_and_exit;        }        rc = xnsynch_destroy(&event->synch_base);#ifdef CONFIG_XENO_OPT_REGISTRY    if (event->handle)        xnregistry_remove(event->handle);#endif /* CONFIG_XENO_OPT_REGISTRY */    xeno_mark_deleted(event);    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_event_signal(RT_EVENT *event,unsigned long mask) * @brief Post an event group. * * Post a set of bits to the event mask. All tasks having their wait * request fulfilled by the posted events are resumed. * * @param event The descriptor address of the affected event. * * @param mask The set of events to be posted. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a event is not an event group descriptor. * * - -EIDRM is returned if @a event is a deleted event group descriptor. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * - User-space task * * Rescheduling: possible. */int rt_event_signal (RT_EVENT *event,		     unsigned long mask){    xnpholder_t *holder, *nholder;    int err = 0, resched = 0;    spl_t s;    xnlock_get_irqsave(&nklock,s);    event = xeno_h2obj_validate(event,XENO_EVENT_MAGIC,RT_EVENT);    if (!event)        {        err = xeno_handle_error(event,XENO_EVENT_MAGIC,RT_EVENT);        goto unlock_and_exit;        }        /* Post the flags. */    event->value |= mask;    /* And wakeup any sleeper having its request fulfilled. */    nholder = getheadpq(xnsynch_wait_queue(&event->synch_base));    while ((holder = nholder) != NULL)        {        RT_TASK *sleeper = thread2rtask(link2thread(holder,plink));        int mode = sleeper->wait_args.event.mode;        unsigned long bits = sleeper->wait_args.event.mask;        if (((mode & EV_ANY) && (bits & event->value) != 0) ||            (!(mode & EV_ANY) && ((bits & event->value) == bits)))            {            sleeper->wait_args.event.mask = (bits & event->value);            nholder = xnsynch_wakeup_this_sleeper(&event->synch_base,holder);            resched = 1;            }        else            nholder = nextpq(xnsynch_wait_queue(&event->synch_base),holder);        }    if (resched)        xnpod_schedule(); unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return err;}/** * @fn int rt_event_wait(RT_EVENT *event,unsigned long mask,unsigned long *mask_r,int mode,RTIME timeout) * @brief Pend on an event group.

⌨️ 快捷键说明

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