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

📄 pod.c

📁 rtai-3.1-test3的源代码(Real-Time Application Interface )
💻 C
📖 第 1 页 / 共 5 页
字号:
 * * Context: This routine must be called on behalf of a thread context. */void xnpod_delete_thread (xnthread_t *thread, xnmutex_t *imutex){    xnsched_t *sched;    spl_t s;    if (testbits(thread->status,XNROOT))	xnpod_fatal("attempt to delete the root thread");    if (nkpod->schedhook)	nkpod->schedhook(thread,XNDELETED);    sched = thread->sched;    splhigh(s);    removeq(&nkpod->threadq,&thread->glink);    if (!testbits(thread->status,XNTHREAD_BLOCK_BITS))	{	if (testbits(thread->status,XNREADY))	    {	    removepq(&sched->readyq,&thread->rlink);	    clrbits(thread->status,XNREADY);	    }	}    else	{	if (testbits(thread->status,XNDELAY))	    xntimer_stop(&thread->timer);	if (testbits(thread->status,XNTHREAD_BLOCK_BITS & ~XNDELAY))	    removeq(&sched->suspendq,&thread->slink);	}    xntimer_stop(&thread->atimer);    /* Ensure the rescheduling can take place if the deleted thread is       the running one. */    if (testbits(thread->status,XNLOCK))	{	clrbits(thread->status,XNLOCK);	xnarch_atomic_set(&nkpod->schedlck,0);	}    if (testbits(thread->status,XNPEND))	xnsynch_forget_sleeper(thread);    xnsynch_release_all_ownerships(thread);#ifdef CONFIG_RTAI_FPU_SUPPORT    if (thread == sched->fpuholder)	sched->fpuholder = NULL;#endif /* CONFIG_RTAI_FPU_SUPPORT */    setbits(thread->status,XNZOMBIE);    if (sched->runthread == thread)	{	/* We first need to elect a new runthread before switching out	   the current one forever. Use the thread zombie state to go	   through the rescheduling procedure then actually destroy	   the thread object. */	setbits(nkpod->status,XNSCHED);	/* The interface mutex will be cleared by the rescheduling           proc. */	xnpod_schedule(imutex);	}    else	{	if (countq(&nkpod->tdeleteq) > 0 &&	    !testbits(thread->status,XNTHREAD_SYSTEM_BITS))	    xnpod_fire_callouts(&nkpod->tdeleteq,thread);	/* Note: the thread control block must remain available until           the user hooks have been called. FIXME: Catch 22 here,           whether we choose to run on an invalid stack (cleanup then           hooks), or to access the TCB space shortly after it has           been freed while non-preemptible (hooks then           cleanup)... Option #2 is current. */	xnthread_cleanup_tcb(thread);	xnarch_finalize_no_switch(xnthread_archtcb(thread));	}    splexit(s);}/*! * \fn int xnpod_suspend_thread(xnthread_t *thread,                                xnflags_t mask,                                xnticks_t timeout,				    xnsynch_t *wchan,				    xnmutex_t *imutex); * \brief Suspend a thread. * * Suspends the execution of a thread according to a given suspensive * condition. This thread will not be eligible for scheduling until it * all the pending suspensive conditions set by this service are * removed by one or more calls to xnpod_resume_thread(). * * @param thread The descriptor address of the suspended thread. * * @param mask The suspension mask specifying the suspensive condition * to add to the thread's wait mask. Possible values usable by the * caller are: * * - XNSUSP. This flag forcibly suspends a thread, regardless of any * resource to wait for. The wchan parameter should not be significant * when using this suspension condition. A reverse call to * xnpod_resume_thread() specifying the XNSUSP bit must be issued to * remove this condition, which is cumulative with other suspension * bits. * * - XNDELAY. This flags denotes a counted delay wait (in ticks) which * duration is defined by the value of the timeout parameter. * * - XNPEND. This flag denotes a wait for a synchronization object to * be signaled. The wchan argument must points to this object. A * timeout value can be passed to bound the wait. This suspension mode * should not be used directly by the upper interface, but rather * through the xnsynch_sleep_on() call. * * @param timeout The timeout which may be used to limit the time the * thread pends for a resource. This value is a wait time given in * ticks.  Passing XN_INFINITE specifies an unbounded wait. All other * values are used to initialize a watchdog timer. * * @param wchan The address of a pended resource. This parameter is * used internally by the synchronization object implementation code * to specify on which object the suspended thread pends. * * @param imutex The address of an interface mutex currently held by * the caller which will be subject to a lock-breaking preemption * before the current thread is actually switched out. The * corresponding kernel mutex will be automatically reacquired by the * nanokernel when the suspended thread is eventually resumed, before * xnpod_suspend_thread() returns to its caller. This parameter only * makes sense for self-suspending threads. Passing NULL when no * lock-breaking preemption is required is valid. See xnpod_schedule() * for more on lock-breaking preemption points. * * @return Returns true if a thread switch took place as a * result of this call, false otherwise. * * Side-effect: A rescheduling immediately occurs if the caller * self-suspends, in which case true is always returned. * * Context: This routine can be called on behalf of a thread or IST * context. */int xnpod_suspend_thread (xnthread_t *thread,			  xnflags_t mask,			  xnticks_t timeout,			  xnsynch_t *wchan,			  xnmutex_t *imutex){    xnsched_t *sched;    spl_t s;    /* This routine must be free both from interrupt preemption AND       mutex ops. */    if (testbits(thread->status,XNSTARTED) &&	testbits(thread->status,XNROOT|XNISVC))	xnpod_fatal("attempt to suspend system thread %s (from %s)",		    thread->name,		    xnpod_current_thread()->name);    if (thread->wchan && wchan)	xnpod_fatal("invalid conjunctive wait on multiple synch. objects");    splhigh(s);    sched = thread->sched;    if (thread == sched->runthread)	{	if (xnpod_locked_p())	    xnpod_fatal("suspensive call issued while the scheduler was locked");	setbits(nkpod->status,XNSCHED);	}    /* We must make sure that we don't clear the wait channel if a       thread is first blocked (wchan != NULL) then forcibly suspended       (wchan == NULL), since these are conjunctive conditions. */    if (wchan)	thread->wchan = wchan;    /* Is the thread ready to run? */    if (!testbits(thread->status,XNTHREAD_BLOCK_BITS))	{	/* A newly created thread is not linked to the ready thread	   queue yet. */	if (testbits(thread->status,XNREADY))	    {	    removepq(&sched->readyq,&thread->rlink);	    clrbits(thread->status,XNREADY);	    }	if ((mask & ~XNDELAY) != 0)	    /* If the thread is forcibly suspended outside the simple	       delay condition, link it to suspension queue. */	    appendq(&sched->suspendq,&thread->slink);	clrbits(thread->status,XNRMID|XNTIMEO|XNBREAK);	}    else if ((mask & ~XNDELAY) != 0 &&	     !testbits(thread->status,XNTHREAD_BLOCK_BITS & ~XNDELAY))	/* If the thread is forcibly suspended while undergoing a	   simple delay condition, link it to suspension queue too. */	appendq(&sched->suspendq,&thread->slink);    setbits(thread->status,mask);    if (timeout != XN_INFINITE)	{	/* Don't start the timer for a thread indefinitely delayed by	   a call to xnpod_suspend_thread(thread,XNDELAY,0,NULL). */	setbits(thread->status,XNDELAY);	xntimer_start(&thread->timer,timeout,XN_INFINITE);	}        if (nkpod->schedhook)	nkpod->schedhook(thread,mask);    if (thread == sched->runthread)	xnpod_schedule(imutex);    splexit(s);    return (thread == sched->runthread);}/*! * \fn void xnpod_resume_thread(xnthread_t *thread,                                xnflags_t mask); * \brief Resume a thread. * * Resumes the execution of a thread previously suspended by one or * more calls to xnpod_suspend_thread(). This call removes a * suspensive condition affecting the target thread. When all * suspensive conditions are gone, the thread is left in a READY state * at which point it becomes eligible anew for scheduling. * * @param thread The descriptor address of the resumed thread. * * @param mask The suspension mask specifying the suspensive condition * to remove from the thread's wait mask. Possible values usable by * the caller are: * * - XNSUSP. This flag removes the explicit suspension condition. This * condition might be additive to the XNPEND condition. * * - XNDELAY. This flag removes the counted delay wait condition. * * - XNPEND. This flag removes the resource wait condition. If a * watchdog is armed, it is automatically disarmed by this call. * * When the thread is eventually resumed by one or more calls to * xnpod_resume_thread(), the caller of xnpod_suspend_thread() in the * awakened thread that suspended itself should check for the * following bits in its own status mask to determine what caused its * wake up: * * - XNRMID means that the caller must assume that the pended * synchronization object has been destroyed (see xnsynch_flush()). * * - XNTIMEO means that the delay elapsed, or the watchdog went off * before the corresponding synchronization object was signaled. * * - XNBREAK means that the wait has been forcibly broken by a call to * xnpod_unblock_thread(). * * Side-effect: This service does not call the rescheduling procedure * but may affect the ready queue. * * Context: This routine can be called on behalf of a thread or IST * context. */void xnpod_resume_thread (xnthread_t *thread,			  xnflags_t mask){    xnsched_t *sched;    spl_t s;    sched = thread->sched;    splhigh(s);    if (testbits(thread->status,XNTHREAD_BLOCK_BITS)) /* Is thread blocked? */	{	clrbits(thread->status,mask); /* Remove suspensive condition(s) */	if (testbits(thread->status,XNTHREAD_BLOCK_BITS)) /* still blocked? */	    {	    if ((mask & XNDELAY) != 0)		{		/* Watchdog fired or break requested -- stop waiting		   for the resource. */		xntimer_stop(&thread->timer);		mask = testbits(thread->status,XNPEND);		if (mask)		    {		    if (thread->wchan)			xnsynch_forget_sleeper(thread);		    if (testbits(thread->status,XNTHREAD_BLOCK_BITS)) /* Still blocked? */			{			splexit(s);			return;			}		    }		else		    {		    /* The thread is still suspended (XNSUSP) */		    splexit(s);		    return;		    }		}	    else if (testbits(thread->status,XNDELAY))		{		if ((mask & XNPEND) != 0)		    {		    /* The thread is woken up due to the availability		       of the requested resource. Cancel the watchdog		       timer. */		    xntimer_stop(&thread->timer);		    clrbits(thread->status,XNDELAY);		    }		if (testbits(thread->status,XNTHREAD_BLOCK_BITS)) /* Still blocked? */		    {		    splexit(s);		    return;		    }		}	    else		{		/* The thread is still suspended, but is no more		   pending on a resource. */		if ((mask & XNPEND) != 0 && thread->wchan)		    xnsynch_forget_sleeper(thread);		splexit(s);		return;		}	    }	else if ((mask & XNDELAY) != 0)	    /* The delayed thread is woken up before the delay	       elapsed. */	    xntimer_stop(&thread->timer);	if ((mask & ~XNDELAY) != 0)	    {	    /* If the thread was actually suspended, remove it from	       the suspension queue -- this allows requests like	       xnpod_suspend_thread(...,thread,XNDELAY,0,...) not to	       run the following code when the suspended thread is	       woken up while undergoing an infinite delay. */	    removeq(&sched->suspendq,&thread->slink);	    if (thread->wchan)		xnsynch_forget_sleeper(thread);	    }	}    else if (testbits(thread->status,XNREADY))	{	removepq(&sched->readyq,&thread->rlink);	clrbits(thread->status,XNREADY);	}    /* The readied thread is always put at the end of its priority       group. */    insertpqf(&sched->readyq,&thread->rlink,thread->cprio);    if (thread == sched->runthread)	{	setbits(thread->status,XNREADY);	splexit(s);	if (nkpod->schedhook &&	    getheadpq(&sched->readyq) != &thread->rlink)	    /* The running thread does not lead no more the ready	       queue. */	    nkpod->schedhook(thread,XNREADY);	}    else if (!testbits(thread->status,XNREADY))	{	setbits(thread->status,XNREADY);	splexit(s);	if (nkpod->schedhook)	    nkpod->schedhook(thread,XNREADY);	}    else	splexit(s);    setbits(nkpod->status,XNSCHED);}/*! * \fn void xnpod_unblock_thread(xnthread_t *thread); * \brief Unblock a thread. * * Breaks the thread out of any wait it is currently in.  This call * removes the XNDELAY and XNPEND suspensive conditions previously put * by xnpod_suspend_thread() on the target thread. If all suspensive * conditions are gone, the thread is left in a READY state at which

⌨️ 快捷键说明

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