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

📄 psc.c

📁 fsmlabs的real time linux的内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * (C) Finite State Machine Labs Inc. 2000 business@fsmlabs.com * * Released under the terms of GPL 2. * Open RTLinux makes use of a patented process described in * US Patent 5,995,745. Use of this process is governed * by the Open RTLinux Patent License which can be obtained from * www.fsmlabs.com/PATENT or by sending email to * licensequestions@fsmlabs.com */#include <linux/module.h>#include <linux/proc_fs.h>#include <linux/irq.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/signal.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/mmu_context.h>#include <rtl_debug.h>#include <rtl_core.h>#include <rtlinux_signal.h>#include <psc.h>#include <rtl_sync.h>#include <rtl_time.h>#include <rtl_sched.h>#include <rtl_fifo.h>#include <arch/rtl_switch.h>/* posix/signal.h defines these.  It's an ugly hack and this * is a ugly workaround. -- Cort */#undef sa_sigaction#undef sa_handler#undef sigactionMODULE_AUTHOR("FSMLabs <support@fsmlabs.com>");MODULE_DESCRIPTION("RTLinux user-level real-time Module");MODULE_LICENSE("GPL v2");#define PSC_DEVNAME "RTLinux user-level IRQ handler"extern long sys_call_table[256];unsigned long sys_ni_syscall;unsigned long __NR_rtf_destroy = 0;unsigned long __NR_rtf_create = 0;struct proc_dir_entry *proc_rtlinux, *proc_sigaction,    *proc_sigprocmask, *proc_gethrtime, *proc_rtf_put,    *proc_rtf_get, *proc_rtf_create, *proc_rtf_destroy;struct irq_thread {	struct rtlinux_sigaction action;	pid_t pid;	pthread_t ptid;} irq_threads[NR_IRQS];struct timer_thread {	struct rtlinux_sigaction action;	pid_t pid;	pthread_t ptid;	struct timer_thread *next;	int pending;} *timer_threads;/* support function for checking signal masks. -Nathan */int rtlinux_sigismember(const rtlinux_sigset_t * set, int sig){	int offset;	unsigned long int value;	if (set == NULL)		return (-1);	if (sig > RTLINUX_SIGMAX) {		errno = EINVAL;		return (-1);	}	offset = (int) ((sig / (sizeof(unsigned long int) * 8)));	value = 1 << (sig % (sizeof(unsigned long int) * 8));	if (((unsigned long int) (set->__val[offset] & value)) > 0)		return (1);	return (0);}int rtlinux_sigemptyset(rtlinux_sigset_t * set){	if (set == NULL)		return (-1);	memset(set, 0x00, sizeof(rtlinux_sigset_t));	return (0);}static void insert_timer_thread(struct timer_thread *thread){	unsigned long flags;	rtl_hard_savef_and_cli(flags);	rtlinux_sigemptyset(&(thread->action.sa_mask));	thread->pending = 0;	thread->next = timer_threads;	timer_threads = thread;	rtl_hard_restore_flags(flags);}static struct timer_thread *remove_timer_thread(struct timer_thread *tt){	unsigned long flags;	struct timer_thread *ret = NULL, *die = NULL;	rtl_hard_savef_and_cli(flags);	if ((tt = timer_threads)) {		timer_threads = timer_threads->next;		goto out;	}	for (ret = timer_threads; ret->next && (ret->next != tt);	     ret = ret->next)		/* nothing */ ;	die = ret->next;	if (ret->next)		ret->next = ret->next->next;	kfree(die);      out:	rtl_hard_restore_flags(flags);	return ret;}static struct timer_thread *find_timer_thread(pid_t pid, int signal){	unsigned long flags;	struct timer_thread *ret;	rtl_hard_savef_and_cli(flags);	for (ret = timer_threads; ret && ((ret->pid != pid) ||		(ret->action.sa_signal != signal)); ret = ret->next)		/* nothing */ ;	rtl_hard_restore_flags(flags);	return ret;}static int call_handler(struct rtlinux_sigaction *act, pid_t pid){	rtl_irqstate_t flags;#ifdef RTL_PSC_NEW	rtl_mmu_state_t mmu_state;#else	struct task_struct *linux_current = get_linux_current();#endif	struct task_struct *tsk;	int ret = 0;	/* make sure the task that wants this interrupt is still running */	if (!(tsk = find_task_by_pid(pid))) {	/* TODO is this really safe? */		/* make sure the handler is disabled */		act->sa_flags |= RTLINUX_SA_ONESHOT;		rtl_printf("task %d is gone!\n", pid);		ret = -1;		goto out;	}	if (!tsk->mm) {		/* make sure the handler is disabled */		act->sa_flags |= RTLINUX_SA_ONESHOT;		rtl_printf("task has no ->mm, not calling\n");		ret = -1;		goto out;	}#ifndef RTL_PSC_NEW	if (!linux_current->active_mm) {		act->sa_flags |= RTLINUX_SA_ONESHOT;		rtl_printf("current has no ->mm, not calling\n");		ret = -1;		goto out;	}#endif	rtl_no_interrupts(flags);	rtl_make_psc_active();#ifdef RTL_PSC_NEW	rtl_mmu_save(&mmu_state);	rtl_mmu_switch_to(tsk);	act->sa_handler(act->sa_signal);	rtl_mmu_restore(&mmu_state);#else	switch_mm(linux_current->active_mm, tsk->mm, tsk, rtl_getcpuid());	act->sa_handler(act->sa_signal);	switch_mm(tsk->mm, linux_current->active_mm, tsk, rtl_getcpuid());#endif	rtl_make_psc_inactive();	rtl_restore_interrupts(flags);      out:	return ret;}static void *psc_irq_thread(void *t){	ulong flags;	struct irq_thread *my_irq_thread = (struct irq_thread *) t;	rtl_stop_interrupts();	while (1) {		pthread_suspend_np(pthread_self());		/* if the handler call fails or we don't want to reset the 		 * handler remove it */		if (call_handler		    (&my_irq_thread->action, my_irq_thread->pid)		    || (my_irq_thread->			action.sa_flags & RTLINUX_SA_ONESHOT)) {			/* we are synchronizing with RTL, so hard cli */			rtl_hard_savef_and_cli(flags);			rtl_free_global_irq(my_irq_thread->					    action.sa_signal);			my_irq_thread->pid = 0;			rtl_hard_restore_flags(flags);		}		rtl_global_pend_irq(my_irq_thread->action.sa_signal);		rtl_hard_enable_irq(my_irq_thread->action.sa_signal);	}}static void *timer_handler(void *t){	struct timer_thread *ptr = (struct timer_thread *) t;	struct sched_param p;	p.sched_priority = 1;	pthread_setschedparam(pthread_self(), SCHED_FIFO, &p);	if (pthread_make_periodic_np(pthread_self(),				     gethrtime() + ptr->action.sa_period,				     ptr->action.sa_period))		    rtl_printf("Error from pthread_make_periodic_np()\n");	while (1) {		pthread_wait_np();		/* if the handler call fails or we don't want to reset the handler		 * remove it		 */		if (ptr->pending == 0) {			if (call_handler(&ptr->action, ptr->pid) ||			    (ptr->action.sa_flags & RTLINUX_SA_ONESHOT)) {				remove_timer_thread(ptr);				pthread_exit(NULL);			}		} else			ptr->pending++;	}	return NULL;}static unsigned int psc_irq_handler(unsigned int irq, struct pt_regs *regs){	/* just wake the stinking IRQ thread up and let it handle it -Nathan */	pthread_wakeup_np(irq_threads[irq].ptid);	return 0;}static int sigaction_write(struct file *file, const char *buffer,			   unsigned long count, void *data){	struct rtlinux_sigaction action;	ulong flags;	struct timer_thread *tt = NULL;	if (count != sizeof(action))		return -EINVAL;	/* make sure the buffer we were passed is good, then copy it */	if (copy_from_user	    ((void *) &action, (void *) buffer,	     sizeof(action))) return -EFAULT;	rtlinux_sigemptyset(&(action.sa_mask));	/* if the signal is < SIGTIMER0 it's an IRQ request */	if (action.sa_signal < RTLINUX_SIGTIMER0) {		/* a request to free the irq */		if ((action.sa_handler == RTLINUX_SIG_DFL) ||		    (action.sa_handler == RTLINUX_SIG_IGN)) {			pthread_kill(irq_threads[action.sa_signal].ptid,				     RTL_SIGNAL_CANCEL);			if (rtl_free_global_irq(action.sa_signal))				return -EALREADY;			else				return count;		}		/* we are synchronizing with RTL, so hard cli */		rtl_hard_savef_and_cli(flags);		/* grab the interrupt */		if (rtl_request_global_irq		    (action.sa_signal, psc_irq_handler)) {			rtl_hard_restore_flags(flags);			return -EBUSY;		}		/* hmm, somehow we need to threadify IRQs so they have state		 * so they can be switched and stuff.  hmmm . . .  -Nathan */		/* we now own the real-time irq, assign the code */		irq_threads[action.sa_signal].pid = current->pid;		irq_threads[action.sa_signal].action = action;		pthread_create(&irq_threads[action.sa_signal].ptid, NULL,			       psc_irq_thread,			       (void *) &irq_threads[action.sa_signal]);#ifdef CONFIG_RTL_FP_SUPPORT

⌨️ 快捷键说明

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