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

📄 rt_ipc.c

📁 fsmlabs的real time linux的内核
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  rt_ipc.c -- intertask communication primitives for Real-Time Linux * *  Copyright (C) 1997 Jerry Epplin.  All rights reserved. * *  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., 675 Mass Ave, Cambridge, MA 02139, USA. * *  History: *   17-Jul-97 jhe  V0.1 Original. *   28-Jul-97 jhe  V0.2 Timeouts on semaphores.  Message queues. *   15-Aug-97 jhe  V0.3 rt_ipc fifos.  Modified semantics of timeouts. */#define IPC_VERSION "0.3"#include <linux/module.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/errno.h>#include <asm/system.h>#include <linux/malloc.h>#include <rtl_sched.h>#include <rtl_sync.h>#include <rtl_fifo.h>#include <asm/rt_irq.h>#include "rt_ipc.h"extern int rtl_schedule(void);#include <rtl_sync.h>#ifdef CONFIG_SMP#error rt_ipc does not work on SMP yetextern spinlock_t fifo_spinlock;#define RTL_SPIN_LOCK fifo_spinlock#endif#define IPC_DATA_INDEX 0/************************************************************************* * rt_sem_init -- initialize a real-time semaphore * * Called to initialize a real-time semaphore.  'sem' must point to a * statically allocated structure.  'type' is RT_SEM_BINARY or  * RT_SEM_COUNTING.  'init_val' is the initial value of the semaphore * (usually 0). * * Returns 0 if successful, -EINVAL if called incorrectly. *************************************************************************/int rt_sem_init(rt_sem_t *sem, RT_SEMTYPE type, int init_val){  int ret = 0;  if (init_val < 0 || (type == RT_SEM_BINARY && init_val > 1))    ret = -EINVAL;		/* binary sem must have 0 or 1 */  else  {    sem->magic = RT_SEM_MAGIC;    sem->val = init_val;    sem->type = type;    sem->wait_list = NULL;  }  return ret;}/************************************************************************* * rt_sem_destroy -- remove a real-time semaphore * * Removes a semaphore previously created with rt_sem_init().  Semaphore * deletion safety is implemented; i.e., any tasks blocked on this  * semaphore when it is destroyed are allowed to run. * * Returns 0 if successful, -EINVAL if 'sem' is not a valid rt_sem_t. *************************************************************************/int rt_sem_destroy(rt_sem_t *sem){  int ret = 0;  if (sem->magic != RT_SEM_MAGIC)    ret = -EINVAL;  else    /* unblock any tasks blocked on this sem */    while (sem->val < 0)      rt_sem_post(sem);  return ret;}/************************************************************************* * unlink_sem_task -- remove a task from a wait list * * Removes a task from the list of tasks waiting on a semaphore. *************************************************************************/static void unlink_sem_task(RT_TASK_ENTRY *to_unlink, rt_sem_t *sem){  if (to_unlink->next != NULL)    to_unlink->next->prev = to_unlink->prev;  if (to_unlink->prev == NULL)    sem->wait_list = to_unlink->next;  else    to_unlink->prev->next = to_unlink->next;}/************************************************************************* * unlink_mq_task -- remove a task from a wait list * * Removes a task from the list of tasks waiting on a message queue. *************************************************************************/static void unlink_mq_task(RT_TASK_ENTRY *to_unlink, rt_mq_t *mq){  if (to_unlink->next != NULL)    to_unlink->next->prev = to_unlink->prev;  if (to_unlink->prev == NULL)    mq->wait_list = to_unlink->next;  else    to_unlink->prev->next = to_unlink->next;}/* cope with the changed priority system */#define GET_PRIO(task) (sched_get_priority_max(0) - (*(task))->sched_param.sched_priority)#define rtl_current (pthread_self()->user[IPC_DATA_INDEX])/* #define rtl_current ((LOCAL_SCHED)-> rtl_current); *//************************************************************************* * rt_sem_post -- semaphore post operation * * The semaphore post (sometimes known as 'give', 'signal', or 'V') operation. * If tasks are waiting for the semaphore, the one with the highest priority * is allowed to run. * * Returns 0 if successful, or -EINVAL if the semaphore is not valid. *************************************************************************/int rt_sem_post(rt_sem_t *sem){  int ret = 0;  int flags;  if (sem->magic != RT_SEM_MAGIC)    ret = -EINVAL;		/* invalid rt_sem_t structure */  else  {    RT_TASK_ENTRY *to_run = NULL;    rtl_critical(flags);    if (sem->val < 0)	/* one or more tasks are waiting for this sem */    {      /* find the waiting task with the highest priority */      RT_TASK_ENTRY *t;      /* search exhaustively all waiting tasks.  I don't want to keep */      /* the list in priority order because I don't want to assume    */      /* the task priorities won't change.                            */      for (t=sem->wait_list ; t!=NULL ; t=t->next)        if (to_run == NULL || GET_PRIO(t->task) < GET_PRIO(to_run->task))          to_run = t;      /* remove the task to be run from the wait_list */      unlink_sem_task(to_run, sem);      /* mark that task as no longer waiting at sem */      ((RT_TASK_IPC *)(to_run->task))->sem_at = NULL;    }    /* binary semaphores never exceed 1 */    if (sem->val < 1 || sem->type == RT_SEM_COUNTING)      ++sem->val;    if (to_run != NULL)    {      /* rt_sem_wait() returned because of a post, not */      /* because of a timeout */      ((RT_TASK_IPC *)(to_run->task))->timed_out = 0;      rt_task_wakeup(to_run->task);    }    rtl_end_critical(flags);  }  return ret;}/************************************************************************* * rt_sem_wait -- semaphore wait operation (blocking) * * The semaphore wait (sometimes known as 'take' or 'P') operation. * If the semaphore is not available, the calling task blocks until * it is.  'timeout' is an optional timeout period.  If 'timeout' is * RT_WAIT_FOREVER, the function does not time out.  If 'timeout' is * RT_NO_WAIT and the semaphore is not available, rt_sem_wait() returns * immediately.  If 'timeout' is any other value, it represent a time  * at which the call to rt_sem_wait() should time out.  If that time * is reached, rt_sem_wait() returns with -ETIME. * * Returns 0 if successful, -ETIME if the operation timed out, -EAGAIN if * RT_NO_WAIT was specified and the semaphore was not available, or -EINVAL * if the semaphore is not valid. *************************************************************************/int rt_sem_wait(rt_sem_t *sem, RTIME timeout){  int ret = 0;  int flags;  if (sem->magic != RT_SEM_MAGIC)    ret = -EINVAL;		/* invalid rt_sem_t structure */  else  {	  rtl_critical(flags);    if (sem->val <= 0)		/* sem not available -- task must wait */    {      if (timeout == RT_NO_WAIT)        ret = -EAGAIN;      else      {        RT_TASK_ENTRY *to_add = &(((RT_TASK_IPC *)rtl_current)->rte);        /* put task on wait_list */        to_add->task = rtl_current;        to_add->prev = NULL;        to_add->next = sem->wait_list;        if (to_add->next != NULL)          to_add->next->prev = to_add;        sem->wait_list = to_add;        /* indicate which sem the task is blocked at */        ((RT_TASK_IPC *)rtl_current)->sem_at = sem;        /* and decrement sem value */        --sem->val;        /* and finally, block */        if (timeout == RT_WAIT_FOREVER)          rt_task_suspend(rtl_current);	/* suspend until post */        else        {          /* assume call timed out.  If this is not the case, */          /* rt_sem_post() will clear this flag */          ((RT_TASK_IPC *)rtl_current)->timed_out = 1;          /* delay until either post occurs or timeout occurs */          rt_task_delay(timeout);          if (((RT_TASK_IPC *)rtl_current)->timed_out)          {            /* timeout occurred -- undo everything and return */            unlink_sem_task(to_add, sem);            ++sem->val;            ret = -ETIME;          }        }      }    }    else      --sem->val;   rtl_end_critical(flags);  }  return ret;}/************************************************************************* * rt_sem_trywait -- semaphore wait operation (unblocking) * * The semaphore wait (sometimes known as 'take' or 'P') operation. * The function returns immediately whether or not the semaphore is * available. * * Returns 0 if successful, -EAGAIN if the semaphore is not available, * or -EINVAL if the semaphore is not valid. *************************************************************************/int rt_sem_trywait(rt_sem_t *sem){  int ret = 0;  int flags;  if (sem->magic != RT_SEM_MAGIC)    ret = -EINVAL;		/* invalid rt_sem_t structure */  else  {	  rtl_critical(flags);    if (sem->val <= 0)		/* sem not available -- task must wait */      ret = -EAGAIN;    else      --sem->val;    rtl_end_critical(flags);  }  return ret;}/************************************************************************* * rt_task_ipc_init -- rt_ipc version of rt_task_init() * * RT-Linux programs using rt_ipc should use rt_task_ipc_init instead of * rt_task_init().  It initializes some rt_ipc variables, then calls * rt_task_init().  Note that all parameters are the same as in rt_task_init() * except 'task', which is an RT_TASK_IPC instead of an RT_TASK. * * Returns 0 if successful, -EINVAL if the 'task' structure is already in * use by another task, or -ENOMEM if a memory allocation error occurred. *************************************************************************/

⌨️ 快捷键说明

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