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

📄 shadow.c

📁 rtai-3.1-test3的源代码(Real-Time Application Interface )
💻 C
📖 第 1 页 / 共 3 页
字号:
	    case __xn_sys_sched:		xnpod_schedule(NULL);		return;	    case __xn_sys_attach:		__xn_reg_rval(regs) = xnshadow_attach_skin(task,							   __xn_reg_arg1(regs),							   __xn_reg_arg2(regs));		return;	    case __xn_sys_detach:		__xn_reg_rval(regs) = xnshadow_detach_skin(task,							   __xn_reg_arg1(regs));		return;	    case __xn_sys_sync:	/* Do this from the Linux domain. */		adeos_propagate_event(evinfo);		return;	    case __xn_sys_migrate:		if (!thread)	/* Not a shadow anyway. */		    __xn_reg_rval(regs) = 0;		else if (__xn_reg_arg1(regs)) /* Linux => RTAI */		    {		    if (!xnthread_test_flags(thread,XNRELAX))			__xn_reg_rval(regs) = 0;		    else			adeos_propagate_event(evinfo);		    }		else	/* RTAI => Linux */		    {		    if (xnthread_test_flags(thread,XNRELAX))			__xn_reg_rval(regs) = 0;		    else			{			__xn_reg_rval(regs) = 1;			xnshadow_relax();			}		    }		return;#if CONFIG_TRACE	    case 20:		TRACE_PROCESS(TRACE_EV_PROCESS_SIGNAL, -888, adp_root->cpudata[0].irq_pending_lo[0]);		__xn_reg_rval(regs) = 0;		return;	    case 21:		TRACE_PROCESS(TRACE_EV_PROCESS_SIGNAL, -999, 0);		__xn_reg_rval(regs) = 0;		return;#endif	    default:		__xn_reg_rval(regs) = -ENOSYS;		return;	    }	}    /* Skin call: check validity. */    if (muxid < 0 || muxid > XENOMAI_MUX_NR ||	muxop < 0 || muxop >= muxtable[muxid - 1].nrcalls ||	((muxtable[muxid - 1].systab[muxop].flags & __xn_flag_anycontext) == 0 &&	 xnshadow_thread(task) == NULL))	{	__xn_reg_rval(regs) = -ENOSYS;	return;	}    if ((muxtable[muxid - 1].systab[muxop].flags & __xn_flag_suspensive) != 0 &&	evinfo->domid != RTAI_DOMAIN_ID)	/* This one must be handled in the Linux domain. */	adeos_propagate_event(evinfo);    else	__xn_reg_rval(regs) = muxtable[muxid - 1].systab[muxop].svc(task,regs);}static void xnshadow_linux_sysentry (adevinfo_t *evinfo){    struct pt_regs *regs = (struct pt_regs *)evinfo->evdata;    xnthread_t *thread = xnshadow_thread(current);    int muxid, muxop;    if (__xn_reg_mux_p(regs))	{	/* muxid and muxop have already been checked in the RTAI	   domain handler. */	muxid = __xn_mux_id(regs);	muxop = __xn_mux_op(regs);#if 1	if (traceme)	    printk("REQ {skin=%d, op=%d} on behalf of thread %s, pid=%d in domain %s\n",		   muxid,		   muxop,		   xnpod_current_thread()->name,		   current->pid,		   adp_current->name);#endif	if (muxid == 0)	    {	    /* These are special built-in services which must be run	       on behalf of the Linux domain. */	    switch (muxop)		{		case __xn_sys_sync:		    __xn_reg_rval(regs) = xnshadow_sync_wait((int *)__xn_reg_arg1(regs));		    break;		case __xn_sys_migrate:		    __xn_reg_rval(regs) = 1;		    xnshadow_harden(NULL);		    return;		}	    }	else	    __xn_reg_rval(regs) = muxtable[muxid - 1].systab[muxop].svc(current,regs);	if (thread && testbits(thread->status,XNAUTOSW|XNRELAX) == (XNAUTOSW|XNRELAX))	    {	    xnshadow_harden(NULL);	    return;	    }	}    else	{	if (thread && xnshadow_substitute_syscall(current,regs,1))	    /* This is a Linux syscall issued on behalf of a shadow	       thread running inside the Linux domain. If the call has	       been substituted with a RTAI replacement, do not let	       Linux know about it. */	    return;	/* Fall back to Linux syscall handling. */	adeos_propagate_event(evinfo);	}}static void xnshadow_linux_sysexit (adevinfo_t *evinfo){    xnthread_t *thread = xnshadow_thread(current);    if (thread && !signal_pending(current))	{#if 1	if (traceme)	    printk("__SYSOUT__ %s, pid=%d, autoswitch=%d\n",		   xnpod_current_thread()->name,		   current->pid,		   testbits(thread->status,XNAUTOSW|XNSYSSW) == (XNAUTOSW|XNSYSSW));#endif	if (testbits(thread->status,XNAUTOSW|XNSYSSW) == (XNAUTOSW|XNSYSSW))	    {	    clrbits(thread->status,XNSYSSW);	    xnshadow_harden(NULL);	    return;	    }	}    adeos_propagate_event(evinfo);}static void xnshadow_linux_taskexit (adevinfo_t *evinfo){    xnthread_t *thread = xnshadow_thread(current);    if (thread)	{#if 1	if (traceme)	    printk("LINUX EXIT on behalf of thread %s, pid=%d, relaxed? %d\n",		   thread->name,		   current->pid,		   !!testbits(thread->status,XNRELAX));#endif	if (xnpod_shadow_p())	    xnshadow_relax();	/* So that we won't attempt to further wakeup the exiting task	   in xnshadow_unmap(). */	xnthread_archtcb(thread)->user_task = NULL;    	xnshadow_ptd(current) = NULL;	xnpod_delete_thread(thread,NULL);#if 1	if (traceme)	    printk("Cleaned up %s\n",thread->name);#endif	}    adeos_propagate_event(evinfo);}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)static struct mmreq {    int in, out, count;#define MAX_MM 32  /* Should be more than enough (must be a power of 2). */#define bump_mmreq(x) do { x = (x + 1) & (MAX_MM - 1); } while(0)    struct mm_struct *mm[MAX_MM];} mmrqtab[NR_CPUS];#endif  /* KERNEL_VERSION < 2.6.0 */static void xnshadow_schedule_head (adevinfo_t *evinfo){    struct { struct task_struct *prev, *next; } *evdata = (__typeof(evdata))evinfo->evdata;    struct task_struct *next = evdata->next;    int rootprio;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)    struct task_struct *prev = evdata->prev;    /* The SCHEDULE_HEAD event is sent by the (Adeosized) Linux kernel       each time it's about to switch a process out. This hook is       aimed at preventing the last active MM from being dropped       during the real-time operations since it is costly.  See       kernel/sched.c (schedule()) for more. The MM dropping is simply       postponed until the SCHEDULE_TAIL event is received, right       after the incoming task has been switched in. */    if (!prev->mm)	{	struct mmreq *p = mmrqtab + task_cpu(prev);	struct mm_struct *oldmm = prev->active_mm;	BUG_ON(p->count >= MAX_MM);	/* Prevent the MM from being dropped in schedule(), then pend	   a request to drop it later in xnshadow_schedule_tail(). */	atomic_inc(&oldmm->mm_count);	p->mm[p->in] = oldmm;	bump_mmreq(p->in);	p->count++;	}#endif  /* KERNEL_VERSION < 2.6.0 */    adeos_propagate_event(evinfo);    if (!nkpod)	return;    if (xnshadow_thread(next))	{	rootprio = xnshadow_thread(next)->cprio;	engage_irq_shield();	}    else if (next != gatekeeper)	{	rootprio = XNPOD_ROOT_PRIO_BASE;	disengage_irq_shield();	}    else	return;    /* Current Xenomai thread must be the root one in this context, so       we can safely renice Xenomai's runthread (i.e. as returned by       xnpod_current_thread()). */    if (xnpod_current_thread()->cprio != rootprio)	xnpod_renice_root(rootprio);}static void xnshadow_schedule_tail (adevinfo_t *evinfo){    if (evinfo->domid == RTAI_DOMAIN_ID)	/* About to resume in xnshadow_harden() after the gatekeeper	   switched us back. Do _not_ propagate this event so that	   Linux's tail scheduling won't be performed. */	return;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)    {    struct mmreq *p;#ifdef CONFIG_PREEMPT    preempt_disable();#endif /* CONFIG_PREEMPT */    p = mmrqtab + smp_processor_id();    while (p->out != p->in)	{	struct mm_struct *oldmm = p->mm[p->out];	mmdrop(oldmm);	bump_mmreq(p->out);	p->count--;	}#ifdef CONFIG_PREEMPT    preempt_enable();#endif /* CONFIG_PREEMPT */    }#endif  /* KERNEL_VERSION < 2.6.0 */    adeos_propagate_event(evinfo);}static void xnshadow_signal_process (adevinfo_t *evinfo){    struct { struct task_struct *task; int sig; } *evdata = (__typeof(evdata))evinfo->evdata;    xnthread_t *thread = xnshadow_thread(evdata->task);    if (thread && !testbits(thread->status,XNRELAX|XNROOT))	{	switch (evdata->sig)	    {	    case SIGTERM:	    case SIGKILL:	    case SIGQUIT:	    case SIGINT:		/* Let the kick handler process those signals, and let		   them propagate. */		break;	    default:		/* Instead of having the shadow threads being marked		   as uninterruptible when running into the RTAI		   domain, which somewhat breaks Linux's activity		   counters, we leave them in an interruptible state,		   but block the signal propagation here when such		   threads remain under the control of the Xenomai		   scheduler. */		return;	    }	}    adeos_propagate_event(evinfo);}static void xnshadow_kick_process (adevinfo_t *evinfo){    struct { struct task_struct *task; } *evdata = (__typeof(evdata))evinfo->evdata;    struct task_struct *task = evdata->task;    xnthread_t *thread = xnshadow_thread(task);    spl_t s;    if (thread && !testbits(thread->status,XNRELAX|XNROOT))	{	/* Some kernel-originated signals do not raise an	   ADEOS_SIGNAL_PROCESS event and cannot be blocked in any way	   (e.g. group exit signal). So we must interpose on the	   ADEOS_KICK_PROCESS event in order to be given a chance to	   see those at least, and unblock their real-time counterpart	   if they happen to target a real-time shadow. This event is	   always propagated and cannot be dismissed, but again, at	   least we have been warned. */	if (sigismember(&task->pending.signal,SIGTERM) ||	    sigismember(&task->pending.signal,SIGKILL) ||	    sigismember(&task->pending.signal,SIGQUIT) ||	    sigismember(&task->pending.signal,SIGINT))	    {	    splhigh(s);	    thread->signals |= XNTHREAD_SHADOW_SIGKILL;	    if (!testbits(thread->status,XNSTARTED))		xnshadow_start(thread,0,NULL,NULL,0);	    else		xnpod_unblock_thread(thread);	    if (testbits(thread->status,XNSUSP))		xnpod_resume_thread(thread,XNSUSP);	    	    xnshadow_schedule(); /* Schedule in the RTAI space. */	    splexit(s);	    }	}}static void xnshadow_renice_process (adevinfo_t *evinfo){    struct { struct task_struct *task; int policy; struct sched_param *param; } *evdata;    xnthread_t *thread;    evdata = (__typeof(evdata))evinfo->evdata;    thread = xnshadow_thread(evdata->task);    if (!thread)	{	adeos_propagate_event(evinfo);	return;	/* Not a shadow -- Let Linux handle this one. */	}    if (evdata->policy != SCHED_FIFO)	/* Bad policy -- Make Linux to ignore the change. */	return;    adeos_propagate_event(evinfo);    xnpod_renice_thread_inner(thread,evdata->param->sched_priority,0);    xnpod_schedule(NULL); /* We are already running into the RTAI domain. */}int xnshadow_register_skin (unsigned magic,			    int nrcalls,			    xnsysent_t *systab){    int muxid;    spl_t s;    /* We can only handle up to 256 syscalls per skin, check for over-       and underflow (MKL) */    if (XNARCH_MAX_SYSENT < nrcalls || 0 > nrcalls)	return -EINVAL;    splhigh(s);    for (muxid = 0; muxid < XENOMAI_MUX_NR; muxid++)	{	if (muxtable[muxid].systab == NULL)	    {	    muxtable[muxid].systab = systab;	    muxtable[muxid].nrcalls = nrcalls;	    muxtable[muxid].magic = magic;	    muxtable[muxid].refcnt = 0;	    splexit(s);	    return muxid + 1;	    }	}    splexit(s);        return -ENOSPC;}int xnshadow_unregister_skin (int muxid){    spl_t s;    if (--muxid < 0 || muxid >= XENOMAI_MUX_NR)	return -EINVAL;    if (muxtable[muxid].refcnt > 0)	return -EBUSY;    splhigh(s);    muxtable[muxid].systab = NULL;    muxtable[muxid].nrcalls = 0;    muxtable[muxid].magic = 0;    splexit(s);    return 0;}static void xnshadow_irq_trampoline (unsigned irq) {    adeos_propagate_irq(irq);}static void xnshadow_shield (int iflag){    unsigned irq;    if (iflag)	for (irq = 0; irq < IPIPE_NR_XIRQS; irq++)	    adeos_virtualize_irq(irq,				 &xnshadow_irq_trampoline,				 NULL,				 IPIPE_DYNAMIC_MASK);    for (;;)	adeos_suspend_domain();}int xnshadow_init (void){    adattr_t attr;    adeos_init_attr(&attr);    attr.name = "Xenomai";    attr.domid = 0x59454e4f;    attr.entry = &xnshadow_shield;    attr.priority = ADEOS_ROOT_PRI + 50;    if (adeos_register_domain(&irq_shield,&attr))	return -EBUSY;    nkgkptd = adeos_alloc_ptdkey();    gkvirq = adeos_alloc_irq();    adeos_virtualize_irq(gkvirq,&xnshadow_wakeup_handler,NULL,IPIPE_HANDLE_MASK);    sigvirq = adeos_alloc_irq();    adeos_virtualize_irq(sigvirq,&xnshadow_signal_handler,NULL,IPIPE_HANDLE_MASK);    nicevirq = adeos_alloc_irq();    adeos_virtualize_irq(nicevirq,&xnshadow_renice_handler,NULL,IPIPE_HANDLE_MASK);    init_MUTEX_LOCKED(&gksync);    init_MUTEX_LOCKED(&gkreq);    kernel_thread((void *)&gatekeeper_thread,NULL,0);    down(&gksync);    adeos_catch_event(ADEOS_SYSCALL_PROLOGUE,&xnshadow_linux_sysentry);    adeos_catch_event(ADEOS_SYSCALL_EPILOGUE,&xnshadow_linux_sysexit);    adeos_catch_event(ADEOS_EXIT_PROCESS,&xnshadow_linux_taskexit);    adeos_catch_event(ADEOS_SIGNAL_PROCESS,&xnshadow_signal_process);    adeos_catch_event(ADEOS_KICK_PROCESS,&xnshadow_kick_process);    adeos_catch_event(ADEOS_SCHEDULE_HEAD,&xnshadow_schedule_head);    adeos_catch_event_from(&rtai_domain,ADEOS_SCHEDULE_TAIL,&xnshadow_schedule_tail);    adeos_catch_event_from(&rtai_domain,ADEOS_SYSCALL_PROLOGUE,&xnshadow_realtime_sysentry);    adeos_catch_event_from(&rtai_domain,ADEOS_RENICE_PROCESS,&xnshadow_renice_process);    return 0;}void xnshadow_cleanup (void){    gkstop = 1;    up(&gkreq);    down(&gksync);    adeos_free_irq(gkvirq);    adeos_free_irq(sigvirq);    adeos_free_irq(nicevirq);    adeos_free_ptdkey(nkgkptd);    adeos_catch_event(ADEOS_SYSCALL_PROLOGUE,NULL);    adeos_catch_event(ADEOS_SYSCALL_EPILOGUE,NULL);    adeos_catch_event(ADEOS_EXIT_PROCESS,NULL);    adeos_catch_event(ADEOS_SIGNAL_PROCESS,NULL);    adeos_catch_event(ADEOS_KICK_PROCESS,NULL);    adeos_catch_event(ADEOS_SCHEDULE_HEAD,NULL);    adeos_catch_event_from(&rtai_domain,ADEOS_SCHEDULE_TAIL,NULL);    adeos_catch_event_from(&rtai_domain,ADEOS_SYSCALL_PROLOGUE,NULL);    adeos_catch_event_from(&rtai_domain,ADEOS_RENICE_PROCESS,NULL);    adeos_unregister_domain(&irq_shield);}/*@}*/EXPORT_SYMBOL(xnshadow_harden);EXPORT_SYMBOL(xnshadow_map);EXPORT_SYMBOL(xnshadow_register_skin);EXPORT_SYMBOL(xnshadow_relax);EXPORT_SYMBOL(xnshadow_start);EXPORT_SYMBOL(xnshadow_ticks2ts);EXPORT_SYMBOL(xnshadow_ticks2tv);EXPORT_SYMBOL(xnshadow_ts2ticks);EXPORT_SYMBOL(xnshadow_tv2ticks);EXPORT_SYMBOL(xnshadow_unmap);EXPORT_SYMBOL(xnshadow_unregister_skin);

⌨️ 快捷键说明

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