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

📄 fifos.c

📁 rtai-3.1-test3的源代码(Real-Time Application Interface )
💻 C
📖 第 1 页 / 共 4 页
字号:
/** * @ingroup fifos * @ingroup fifos_ipc * @ingroup fifos_sem * @file * * Implementation of the @ref fifos "RTAI FIFO module". * * @author Paolo Mantegazza * * @note Copyright &copy; 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it> * * 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. *//* ACKNOWLEDGEMENTS: - nice proc file contributed by Steve Papacharalambous (stevep@zentropix.com);- added proc handler info contributed by Rich Walker (rw@shadow.org.uk)- 11-19-2001, Truxton Fulton (trux@truxton.com) fixed a race in mbx_get.- 10-23-2003 added atomic send contributed by Jan Kiszka   (kiszka@rts.uni-hannover.de) and expanded it to rtf_get_if.- 12-10-2003 a fix of rtf_resize odds contributed by Abramo Bagnara  (abramo.bagnara@tin.it).*//** * @defgroup fifos RTAI FIFO module * * See @ref fifos_overview "the general overview of RTAI fifos". *//** * @ingroup fifos * @defgroup fifos_ipc Inter-process communications. * * RTAI FIFO communication functions. * * RTAI fifos maintain full compatibility with those available in NMT_RTLinux * while adding many other useful services that avoid the clumsiness of * Unix/Linux calls. So if you need portability you should bent yourself to the * use of select for timing out IO operations, while if you have not to satisfy * such constraints use the available simpler, and more direct, RTAI fifos * specific services. * * In the table below the standard Unix/Linux services in user space are * enclosed in []. See standard Linux man pages if you want to use them, they * need not be explained here. * * <CENTER><TABLE> * <TR><TD> Called from RT task </TD><TD> Called from Linux process </TD></TR> * <TR><TD> #rtf_create         </TD><TD> #rtf_open_sized           <BR> *                                         [open]                   </TD></TR> * <TR><TD> #rtf_destroy        </TD><TD>  [close]                  </TD></TR> * <TR><TD> #rtf_reset          </TD><TD> #rtf_reset                </TD></TR> * <TR><TD> #rtf_resize         </TD><TD> #rtf_resize               </TD></TR> * <TR><TD> #rtf_get            </TD><TD>  [read]                   <BR> *                                        #rtf_read_timed           <BR> *                                        #rtf_read_all_at_once     </TD></TR> * <TR><TD> #rtf_put            </TD><TD>  [write]                  <BR> *                                        #rtf_write_timed          </TD></TR> * <TR><TD> #rtf_create_handler </TD><TD>                           </TD></TR> * <TR><TD>                     </TD><TD> #rtf_suspend_timed        </TD></TR> * <TR><TD>                     </TD><TD> #rtf_set_async_sig        </TD></TR> * </TABLE></CENTER> * * In Linux, fifos have to be created by : * @verbatim $ mknod /dev/rtf<x> c 150 <x> @endverbatim * where \<x\> is the minor device number, from 0 to 63; thus on the Linux side * RTL fifos can be used as standard character devices. As it was said above to * use standard IO operations on such devices there is no need to explain * anything, go directly to Linux man pages. RTAI fifos specific services * available in kernel and user space are instead explained here. * * What is important to remember is that in the user space side you address * fifos through the file descriptor you get at fifo device opening while in * kernel space you directly address them by their minor number. So you will * mate the @a fd you get in user space by using * @verbatim open(/dev/rtfxx,...) @endverbatim * to the integer @p xx you will use in kernel space. * * @note RTAI fifos should be used just with applications that use only real * time interrupt handlers, so that no RTAI scheduler is installed, or if you * need compatibility with NMT RTL.  If you are working with any RTAI scheduler * already installed you are strongly invited to think about avoiding them, use * LXRT instead. * * It is far better and flexible, and if you really like it the fifos way * mailboxes are a one to one, more effective, substitute.   After all RTAI * fifos are implemented on top of them. *//** * @ingroup fifos * @defgroup fifos_sem Semaphores. * * RTAI FIFO semaphore functions. * * Fifos have an embedded synchronization capability, however using them only * for such a purpose can be clumsy. So RTAI fifos have binary semaphores for * that purpose. Note that, as for put and get fifos functions, only nonblocking * functions are available in kernel space. *  * <CENTER><TABLE> * <TR><TD> Called from RT task </TD><TD> Called from Linux process </TD></TR> * <TR><TD> #rtf_sem_init       </TD><TD> #rtf_sem_init             </TD></TR> * <TR><TD> #rtf_sem_post       </TD><TD> #rtf_sem_post             </TD></TR> * <TR><TD> #rtf_sem_trywait    </TD><TD> #rtf_sem_wait             <BR> *                                        #rtf_sem_trywait          <BR> *                                        #rtf_sem_timed_wait       </TD></TR> * <TR><TD> #rtf_sem_destroy    </TD><TD> #rtf_sem_destroy          </TD></TR> * </TABLE></CENTER> * * To add a bit of confusion (J), with respect to RTAI schedulers semaphore * functions, fifos semaphore functions names follow the POSIX mnemonics. * * It should be noted that semaphores are associated to a fifo for * identification purposes. So it is once more important to remember is that * in the user space side you address fifos through the file descriptor you get * at fifo device opening while in kernel space you directly address them by * their minor number.   So you will mate the fd  you get in user space by * @verbatim open(/dev/rtfxx,) @endverbatim to the integer @p xx youll use in * kernel space. */#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/vmalloc.h>#include <linux/poll.h>#include <linux/termios.h>#include <linux/tty_driver.h>#include <linux/console.h>#include <linux/config.h>#include <linux/slab.h>#include <linux/devfs_fs_kernel.h>#include <linux/stat.h>#include <linux/proc_fs.h>#include <rtai_fifos.h>#include <rtai_trace.h>#include <rtai_proc_fs.h>#include <rtai_sched.h>#include <rtai_lxrt.h>MODULE_LICENSE("GPL");/* these are copied from <rt/rt_compat.h> */#define rtf_save_flags_and_cli(x)	do{x=rt_spin_lock_irqsave(&rtf_lock);}while(0)#define rtf_restore_flags(x)		rt_spin_unlock_irqrestore((x),&rtf_lock)#define rtf_spin_lock_irqsave(x,y)	do{x=rt_spin_lock_irqsave(&(y));}while(0)#define rtf_spin_unlock_irqrestore(x,y)	rt_spin_unlock_irqrestore((x),&(y))#define rtf_request_srq(x)		rt_request_srq(0, (x), 0)#define rtf_free_srq(x)			rt_free_srq((x))#define rtf_pend_srq(x)			rt_pend_linux_srq((x))#ifdef CONFIG_PROC_FSstatic int rtai_proc_fifo_register(void);static void rtai_proc_fifo_unregister(void);#endiftypedef struct lx_queue {	struct lx_queue *prev;	struct lx_queue *next;	struct lx_task_struct *task;} F_QUEUE;typedef struct lx_semaphore {	int free;	int qtype;	F_QUEUE queue;} F_SEM;typedef struct lx_task_struct {	int blocked;	int priority;	F_QUEUE queue;	struct task_struct *task;} LX_TASK;typedef struct lx_mailbox {	int size;   // size of the entire buffer	int fbyte;  // head	int lbyte;  // tail	int avbs;   // bytes available in the buffer	int frbs;   // free bytes in the buffer	char *bufadr;	F_SEM sndsem, rcvsem;	struct task_struct *waiting_task;	spinlock_t buflock;} F_MBX;typedef struct rt_fifo_struct {	F_MBX mbx;		// MUST BE THE FIRST!	int opncnt;	int malloc_type;	int pol_asyn_pended;	wait_queue_head_t pollq;	struct fasync_struct *asynq;	int (*handler)(unsigned int arg);	F_SEM sem;	char name[RTF_NAMELEN+1];} FIFO;static int fifo_srq, async_sig;static spinlock_t rtf_lock = SPIN_LOCK_UNLOCKED;static spinlock_t rtf_name_lock = SPIN_LOCK_UNLOCKED;#define MAX_FIFOS 64//static FIFO fifo[MAX_FIFOS] = {{{0}}};static FIFO *fifo;#define MAXREQS 64	// KEEP IT A POWER OF 2!!!static struct { int in, out; struct task_struct *task[MAXREQS]; } taskq;static struct { int in, out; FIFO *fifo[MAXREQS]; } pol_asyn_q;static RT_TASK *rt_base_linux_task;static int do_nothing(unsigned int arg) { return 0; }static inline void enqueue_blocked(LX_TASK *task, F_QUEUE *queue, int qtype, int priority){	F_QUEUE *q;	task->blocked = 1;	q = queue;	if (!qtype) {		while ((q = q->next) != queue && (q->task)->priority >= priority);	}	q->prev = (task->queue.prev = q->prev)->next  = &(task->queue);	task->queue.next = q;}static inline void dequeue_blocked(LX_TASK *task){	task->blocked = 0;	(task->queue.prev)->next = task->queue.next;	(task->queue.next)->prev = task->queue.prev;}static inline void mbx_sem_signal(F_SEM *sem, FIFO *fifop){	unsigned long flags;	LX_TASK *task;	rtf_save_flags_and_cli(flags);	if ((task = (sem->queue.next)->task)) {		dequeue_blocked(task);		taskq.task[taskq.in] = task->task;		taskq.in = (taskq.in + 1) & (MAXREQS - 1);		rtf_pend_srq(fifo_srq);	} else {		sem->free = 1;		if (fifop && !(fifop->pol_asyn_pended) &&		    (((F_MBX *)fifop)->avbs || ((F_MBX *)fifop)->frbs) &&		    (waitqueue_active(&fifop->pollq) || fifop->asynq)) {			fifop->pol_asyn_pended = 1;			pol_asyn_q.fifo[pol_asyn_q.in] = fifop;			pol_asyn_q.in = (pol_asyn_q.in + 1) & (MAXREQS - 1);			rtf_pend_srq(fifo_srq);		}	}	rtf_restore_flags(flags);	return;}static inline void mbx_signal(F_MBX *mbx){	unsigned long flags;	struct task_struct *task;	rtf_save_flags_and_cli(flags);	if ((task = mbx->waiting_task)) {		mbx->waiting_task = 0;		taskq.task[taskq.in] = task;		taskq.in = (taskq.in + 1) & (MAXREQS - 1);		rtf_pend_srq(fifo_srq);	}	rtf_restore_flags(flags);	return;}static inline int mbx_sem_wait_if(F_SEM *sem){	unsigned long flags;	rtf_save_flags_and_cli(flags);	if (sem->free) {		sem->free = 0;		rtf_restore_flags(flags);		return 1;	}	rtf_restore_flags(flags);	return 0;}static inline int mbx_sem_wait(F_SEM *sem){	unsigned long flags;	LX_TASK task;	int ret;	ret = 0;	rtf_save_flags_and_cli(flags);	if (!sem->free) {		task.queue.task = &task;		task.priority = current->rt_priority;		enqueue_blocked(&task, &sem->queue, sem->qtype, task.priority);		task.task = current;		rtf_restore_flags(flags);		current->state = TASK_INTERRUPTIBLE;		schedule();		if (signal_pending(current)) {			ret = -ERESTARTSYS;		}		rtf_save_flags_and_cli(flags);		if (task.blocked) { 			dequeue_blocked(&task);			if (!(sem->queue.next)->task) {				sem->free = 1;			}			rtf_restore_flags(flags);			if (!ret) {				ret = -1;			}		}	} else {		sem->free = 0;	}	rtf_restore_flags(flags);	return ret;}static inline int mbx_wait(F_MBX *mbx, int *fravbs){	unsigned long flags;	rtf_save_flags_and_cli(flags);	if (!(*fravbs)) {		mbx->waiting_task = current;		current->state = TASK_INTERRUPTIBLE;		rtf_restore_flags(flags);		schedule();		if (signal_pending(current)) {			return -ERESTARTSYS;		}		rtf_save_flags_and_cli(flags);		if (mbx->waiting_task == current) {			mbx->waiting_task = 0;			rtf_restore_flags(flags);			return -1;		}	}	rtf_restore_flags(flags);	return 0;}static inline int mbx_sem_wait_timed(F_SEM *sem, int delay){	unsigned long flags;	LX_TASK task;	rtf_save_flags_and_cli(flags);	if (!sem->free) {		task.queue.task = &task;		task.priority = current->rt_priority;		enqueue_blocked(&task, &sem->queue, sem->qtype, task.priority);		task.task = current;		rtf_restore_flags(flags);		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(delay);		if (signal_pending(current)) {			return -ERESTARTSYS;		}		rtf_save_flags_and_cli(flags);		if (task.blocked) { 			dequeue_blocked(&task);			if (!((sem->queue.next)->task)) {				sem->free = 1;			}			rtf_restore_flags(flags);			return -1;		}	} else {		sem->free = 0;	}	rtf_restore_flags(flags);	return 0;}static inline int mbx_wait_timed(F_MBX *mbx, int *fravbs, int delay){	unsigned long flags;	rtf_save_flags_and_cli(flags);	if (!(*fravbs)) {		mbx->waiting_task = current;		rtf_restore_flags(flags);		current->state = TASK_INTERRUPTIBLE;		schedule_timeout(delay);		if (signal_pending(current)) {			return -ERESTARTSYS;		}		rtf_save_flags_and_cli(flags);		if (mbx->waiting_task == current) {;			mbx->waiting_task = 0;			rtf_restore_flags(flags);			return -1;		}	}	rtf_restore_flags(flags);	return 0;}#define MOD_SIZE(indx) ((indx) < mbx->size ? (indx) : (indx) - mbx->size)static inline int mbx_put(F_MBX *mbx, char **msg, int msg_size, int lnx){	unsigned long flags;	int tocpy;	while (msg_size > 0 && mbx->frbs) {		if ((tocpy = mbx->size - mbx->lbyte) > msg_size) {			tocpy = msg_size;		}		if (tocpy > mbx->frbs) {			tocpy = mbx->frbs;		}		if (lnx) {			copy_from_user(mbx->bufadr + mbx->lbyte, *msg, tocpy);		} else {			memcpy(mbx->bufadr + mbx->lbyte, *msg, tocpy);		}		rtf_spin_lock_irqsave(flags, mbx->buflock);		mbx->lbyte = MOD_SIZE(mbx->lbyte + tocpy);		mbx->frbs -= tocpy;		mbx->avbs += tocpy;		rtf_spin_unlock_irqrestore(flags, mbx->buflock);		msg_size -= tocpy;		*msg     += tocpy;	}	return msg_size;}static inline int mbx_ovrwr_put(F_MBX *mbx, char **msg, int msg_size, int lnx){	unsigned long flags;	int tocpy,n;	if ((n = msg_size - mbx->size) > 0) {		*msg += n;		msg_size -= n;	}			while (msg_size > 0) {		if (mbx->frbs) {				if ((tocpy = mbx->size - mbx->lbyte) > msg_size) {				tocpy = msg_size;			}			if (tocpy > mbx->frbs) {				tocpy = mbx->frbs;			}			if (lnx) {				copy_from_user(mbx->bufadr + mbx->lbyte, *msg, tocpy);			} else {				memcpy(mbx->bufadr + mbx->lbyte, *msg, tocpy);			}			rtf_spin_lock_irqsave(flags, mbx->buflock);			mbx->frbs -= tocpy;			mbx->avbs += tocpy;			rtf_spin_unlock_irqrestore(flags, mbx->buflock);			msg_size -= tocpy;			*msg     += tocpy;			mbx->lbyte = MOD_SIZE(mbx->lbyte + tocpy);		}	

⌨️ 快捷键说明

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