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

📄 pod.c

📁 rtai-3.1-test3的源代码(Real-Time Application Interface )
💻 C
📖 第 1 页 / 共 5 页
字号:
/*!\file pod.c * \brief Real-time pod services. * \author Philippe Gerum * * Copyright (C) 2001,2002,2003 Philippe Gerum <rpm@xenomai.org>. * * Xenomai 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. * * Xenomai 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 Xenomai; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * As a special exception, the RTAI project gives permission * for additional uses of the text contained in its release of * Xenomai. * * The exception is that, if you link the Xenomai libraries with other * files to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public License. * Your use of that executable is in no way restricted on account of * linking the Xenomai libraries code into it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the GNU General Public * License. * * This exception applies only to the code released by the * RTAI project under the name Xenomai.  If you copy code from other * RTAI project releases into a copy of Xenomai, as the General Public * License permits, the exception does not apply to the code that you * add in this way.  To avoid misleading anyone as to the status of * such modified files, you must delete this exception notice from * them. * * If you write modifications of your own for Xenomai, it is your * choice whether to permit this exception to apply to your * modifications. If you do not wish that, delete this exception * notice. * * \ingroup pod *//*! * \defgroup xenomai Xenomai scheduler. * * A scheduler for mimicking real-time operating systems. * * Xenomai is an RTAI scheduler which provides generic real-time operating * services suited for the implementation of real-time operating system * interfaces. *//*! * \ingroup xenomai * \defgroup pod Real-time pod services. * * Real-time pod services. *@{*/#define XENO_POD_MODULE#include <stdarg.h>#include "rtai_config.h"#include "xenomai/pod.h"#include "xenomai/mutex.h"#include "xenomai/synch.h"#include "xenomai/heap.h"#include "xenomai/intr.h"#include "xenomai/module.h"xnpod_t *nkpod = NULL;xnintr_t nkclock;const char *xnpod_fatal_helper (const char *format, ...){    static char buf[256];    xnholder_t *holder;    va_list ap;    spl_t s;    splhigh(s);    va_start(ap,format);    vsprintf(buf,format,ap);    va_end(ap);    if (!nkpod || testbits(nkpod->status,XNFATAL))	goto out;    setbits(nkpod->status,XNFATAL);    xntimer_freeze();    xnprintf("--%-12s PRI   STATUS\n","THREAD");    holder = getheadq(&nkpod->threadq);    while (holder)	{	xnthread_t *thread = link2thread(holder,glink);	xnprintf("%c %-12s %4d  0x%lx\n",		 thread == xnpod_current_thread() ? '>' : ' ',		 thread->name,		 thread->cprio,thread->status);	holder = nextq(&nkpod->threadq,holder);	}    if (testbits(nkpod->status,XNTIMED))	{	if (testbits(nkpod->status,XNTMPER))	    xnprintf("Timer: periodic [tickval=%luus, elapsed=%Lu]\n",		     xnpod_get_tickval() / 1000,		     nkpod->jiffies);	else	    xnprintf("Timer: aperiodic.\n");	}    else	xnprintf("Timer: none.\n"); out:    splexit(s);    return buf;}/* * xnpod_fault_handler -- The default fault handler. */static int xnpod_fault_handler (xnarch_fltinfo_t *fltinfo){    if (!xnpod_userspace_p())	{	xnprintf("Xenomai: suspending kernel thread %p ('%s') at 0x%lx after exception #%u\n",		 xnpod_current_thread(),		 xnpod_current_thread()->name,		 xnarch_fault_pc(fltinfo),		 xnarch_fault_trap(fltinfo));	/* Put the faulting thread in dormant state since XNSUSP might	   be cleared as the application continues. */	xnpod_suspend_thread(xnpod_current_thread(),XNDORMANT,XN_INFINITE,NULL,NULL);	return 1;	}#ifdef __KERNEL__    /* If we experienced a trap on behalf of a shadow thread, just       move the second to the Linux domain, so that the host O/S       (e.g. Linux) can attempt to process the first. This is       especially useful in order to handle user-space errors       gracefully. */    if (xnpod_shadow_p())	{	xnshadow_relax();	return 1;	}#endif /* __KERNEL__ */    return 0;}static void xnpod_host_tick (void *cookie) { /* Host tick relay handler */    xnarch_relay_tick();}/*!  * \fn void xnpod_init(xnpod_t *pod, int minpri, int maxpri, xnflags_t flags); * \brief Initialize a new pod. * * Initializes a new pod which can subsequently be used to start * real-time activities. Once a pod is active, real-time APIs can be * stacked over. There can only be a single pod active in the host * environment. Such environment can be confined to a process though * (e.g. MVM or POSIX layers), or expand to the whole system * (e.g. Adeos or RTAI). * * @param pod The address of a pod descriptor Xenomai will use to * store the pod-specific data.  This descriptor must always be valid * while the pod is active therefore it must be allocated in permanent * memory. * * @param minpri The value of the lowest priority level which is valid * for threads created on behalf of this pod. * * @param maxpri The value of the highest priority level which is * valid for threads created on behalf of this pod. * * @param flags A set of creation flags affecting the operation.  The * only defined flag is XNDREORD (Disable REORDering), which tells the * nanokernel that the (xnsynch_t) pend queue should not be reordered * whenever the priority of a blocked thread it holds is changed. If * this flag is not specified, changing the priority of a blocked * thread using xnpod_renice_thread() will cause the pended queue to * be reordered according to the new priority level, provided the * synchronization object makes the waiters wait by priority order on * the awaited resource (XNSYNCH_PRIO). * * minpri might be numerically higher than maxpri if the upper * real-time interface exhibits a reverse priority scheme. For * instance, some APIs may define a range like minpri=255, maxpri=0 * specifying that thread priorities increase as the priority level * decreases numerically. * * Context: This routine must be called on behalf of a context * allowing immediate memory allocation requests (e.g. an * init_module() routine). */int xnpod_init (xnpod_t *pod, int minpri, int maxpri, xnflags_t flags){    xnsched_t *sched;    u_long rem;    int rc, n;    nkpod = pod;    if (minpri > maxpri)	/* The lower the value, the higher the priority */	flags |= XNRPRIO;    /* Flags must be set before xnpod_get_qdir() is called */    pod->status = (flags & (XNRPRIO|XNDREORD));    initq(&xnmod_glink_queue);    initq(&pod->threadq);    initq(&pod->tstartq);    initq(&pod->tswitchq);    initq(&pod->tdeleteq);    for (n = 0; n < XNTIMER_WHEELSIZE; n++)	initq(&pod->timerwheel[n]);    xntimer_init(&pod->htimer,&xnpod_host_tick,NULL);    xnarch_atomic_set(&pod->schedlck,0);    pod->minpri = minpri;    pod->maxpri = maxpri;    pod->jiffies = 0;    pod->wallclock = 0;    pod->tickvalue = XNARCH_DEFAULT_TICK;    pod->ticks2sec = xnarch_ulldiv(1000000000LL,XNARCH_DEFAULT_TICK,&rem);    pod->svctable.shutdown = &xnpod_shutdown;    pod->svctable.settime = &xnpod_set_time;    pod->svctable.tickhandler = NULL;    pod->svctable.faulthandler = &xnpod_fault_handler;    pod->schedhook = NULL;    pod->latency = xnarch_ns_to_tsc(XNARCH_SCHED_LATENCY);    sched = &pod->sched;    initq(&sched->suspendq);    initpq(&sched->readyq,xnpod_get_qdir(pod));    sched->inesting = 0;    sched->runthread = NULL;	/* This fools xnheap_init() */    sched->usrthread = NULL;    pod->root_prio_base = xnpod_get_minprio(pod,1);    pod->isvc_prio_idle = xnpod_get_minprio(pod,2);    if (xnheap_init(&kheap,NULL,XNPOD_HEAPSIZE,XNPOD_PAGESIZE) != XN_OK)	return XNERR_NOMEM;    /* Create the root thread -- it might be a placeholder for the       current context or a real thread, it depends on the real-time       layer. */    rc = xnthread_init(&sched->rootcb,		       "ROOT",		       XNPOD_ROOT_PRIO_BASE,		       XNROOT|XNSTARTED#ifdef CONFIG_RTAI_FPU_SUPPORT		       /* If the host environment has a FPU, the root			  thread must care for the FPU context. */		       |XNFPU#endif /* CONFIG_RTAI_FPU_SUPPORT */		       ,		       XNARCH_ROOT_STACKSZ,		       NULL,		       0);    if (rc)	return rc;    sched->runthread = &sched->rootcb;    sched->usrthread = &sched->rootcb;#ifdef CONFIG_RTAI_FPU_SUPPORT    sched->fpuholder = &sched->rootcb;#endif /* CONFIG_RTAI_FPU_SUPPORT */    appendq(&pod->threadq,&sched->rootcb.glink);    xnarch_init_root_tcb(xnthread_archtcb(&sched->rootcb),			 &sched->rootcb,			 xnthread_name(&sched->rootcb));    xnarch_notify_ready();    return XN_OK;}/*!  * \fn void xnpod_shutdown(int xtype); * \brief Default shutdown handler. * * Forcibly shutdowns the active pod. All existing nanokernel threads * (but the root one) are terminated, and the system heap is freed. * * @param xtype An exit code passed to the host environment who * started the nanokernel. Zero is always interpreted as a successful * return. * * The nanokernel will not call this routine directly but rather use * the routine pointed at by the pod.svctable.shutdown member in the * service table. This allows upper interfaces to interpose their own * shutdown handlers so that they have their word before any action is * taken. Usually, the interface-defined handlers should end up * calling xnpod_shutdown() after their own housekeeping chores have * been carried out. * * Context: This routine must be called on behalf of the root thread * (e.g. a cleanup_module() routine). */void xnpod_shutdown (int xtype){    xnholder_t *holder, *nholder;    xnthread_t *thread;    spl_t s;    if (!nkpod)	return;	/* No-op */    xnpod_stop_timer();    splhigh(s);    nholder = getheadq(&nkpod->threadq);    while ((holder = nholder) != NULL)	{	nholder = nextq(&nkpod->threadq,holder);	thread = link2thread(holder,glink);	if (!testbits(thread->status,XNROOT))	    xnpod_delete_thread(thread,NULL);	}    splexit(s);    xnheap_destroy(&kheap);    xntimer_destroy(&nkpod->htimer);    nkpod = NULL;}static inline void xnpod_fire_callouts (xnqueue_t *hookq, xnthread_t *thread){    xnholder_t *holder, *nholder;    setbits(nkpod->status,XNKCOUT);    /* The callee is allowed to alter the hook queue when running */    nholder = getheadq(hookq);    while ((holder = nholder) != NULL)	{	xnhook_t *hook = link2hook(holder);	nholder = nextq(hookq,holder);	hook->routine(thread);	}    clrbits(nkpod->status,XNKCOUT);}/*!  * \fn void xnpod_preempt_current_thread(void); * \brief Preempts the current thread - INTERNAL. * * Preempts the running thread (because a more prioritary thread has * just been readied).  The thread is re-inserted at the front of its * priority group in the ready thread queue. */static inline void xnpod_preempt_current_thread (void){    xnthread_t *thread;    xnsched_t *sched;    spl_t s;    sched = xnpod_current_sched();    thread = sched->runthread;    splhigh(s);    insertpql(&sched->readyq,&thread->rlink,thread->cprio);    setbits(thread->status,XNREADY);    setbits(nkpod->status,XNSCHED);    splexit(s);    if (!nkpod->schedhook)	return;    if (getheadpq(&sched->readyq) != &thread->rlink)	nkpod->schedhook(thread,XNREADY);    else if (countpq(&sched->readyq) > 1)	{	/* The running thread is still heading the ready queue and	   more than one thread is linked to this queue, so we may	   refer to the following element as a thread object

⌨️ 快捷键说明

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