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

📄 task.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 5 页
字号:
/** * @file * This file is part of the Xenomai project. * * @note Copyright (C) 2004 Philippe Gerum <rpm@xenomai.org>  * * 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. * * \ingroup task *//*! * \ingroup native * \defgroup task Task management services. * * Xenomai provides a set of multitasking mechanisms. The basic process * object performing actions in Xenomai is a task, a logically complete * path of application code. Each Xenomai task is an independent portion * of the overall application code embodied in a C procedure, which * executes on its own stack context. * * The Xenomai scheduler ensures that concurrent tasks are run according * to one of the supported scheduling policies. Currently, the Xenomai * scheduler supports fixed priority-based FIFO and round-robin * policies. * *@{*/#include <nucleus/pod.h>#include <nucleus/heap.h>#include <nucleus/registry.h>#include <native/task.h>static DECLARE_XNQUEUE(__xeno_task_q);static u_long __xeno_task_stamp;static void __task_delete_hook (xnthread_t *thread){    /* The scheduler is locked while hooks are running. */    RT_TASK *task;    if (xnthread_get_magic(thread) != XENO_SKIN_MAGIC)	return;    task = thread2rtask(thread);#ifdef CONFIG_XENO_OPT_NATIVE_MPS    /* The nucleus will reschedule as needed when all the deletion       hooks are done. */    xnsynch_destroy(&task->mrecv);    xnsynch_destroy(&task->msendq);#endif /* CONFIG_XENO_OPT_NATIVE_MPS */#ifdef CONFIG_XENO_OPT_REGISTRY    if (xnthread_handle(&task->thread_base) != XN_NO_HANDLE)        xnregistry_remove(xnthread_handle(&task->thread_base));#endif /* CONFIG_XENO_OPT_REGISTRY */    xnsynch_destroy(&task->safesynch);    removeq(&__xeno_task_q,&task->link);    xeno_mark_deleted(task);    if (xnthread_test_flags(&task->thread_base,XNSHADOW))	xnfreesafe(&task->thread_base,task,&task->link);}u_long __native_task_safe (void){    RT_TASK *task = xeno_current_task();    return ++task->safelock;}u_long __native_task_unsafe (void){    /* Must be called nklock locked, interrupts off. */    RT_TASK *task = xeno_current_task();    u_long safelock;    if (task->safelock > 0 &&	--task->safelock == 0 &&	xnsynch_nsleepers(&task->safesynch) > 0)	{	xnsynch_flush(&task->safesynch,0);	xnpod_schedule();	}    safelock = task->safelock;    return safelock;}int __native_task_safewait (RT_TASK *task){    /* Must be called nklock locked, interrupts off. */    u_long cstamp;    if (task->safelock == 0)	return 0;    if (task == xeno_current_task())	return -EDEADLK;        cstamp = task->cstamp;    do	{	xnsynch_sleep_on(&task->safesynch,TM_INFINITE);	if (xnthread_test_flags(&xeno_current_task()->thread_base,XNBREAK))	    return -EINTR;	}    while (task->safelock > 0);    if (task->cstamp != cstamp)	return -EIDRM;    return 0;}int __native_task_pkg_init (void){    xnpod_add_hook(XNHOOK_THREAD_DELETE,&__task_delete_hook);    return 0;}void __native_task_pkg_cleanup (void){    xnholder_t *holder;    while ((holder = getheadq(&__xeno_task_q)) != NULL)	rt_task_delete(link2rtask(holder));    xnpod_remove_hook(XNHOOK_THREAD_DELETE,&__task_delete_hook);}/** * @fn int rt_task_create(RT_TASK *task,const char *name,int stksize,int prio,int mode) * @brief Create a new real-time task. * * Creates a real-time task, either running in a kernel module or in * user-space depending on the caller's context. * * @param task The address of a task descriptor Xenomai will use to store * the task-related data.  This descriptor must always be valid while * the task is active therefore it must be allocated in permanent * memory. * * The task is left in an innocuous state until it is actually started * by rt_task_start(). * * @param name An ASCII string standing for the symbolic name of the * task. When non-NULL and non-empty, this string is copied to a safe * place into the descriptor, and passed to the registry package if * enabled for indexing the created task. * * @param stksize The size of the stack (in bytes) for the new * task. If zero is passed, a reasonable pre-defined size will be * substituted. * * @param prio The base priority of the new task. This value must * range from [1 .. 99] (inclusive) where 1 is the lowest effective * priority. * * @param mode The task creation mode. The following flags can be * OR'ed into this bitmask, each of them affecting the new task: * * - T_FPU allows the task to use the FPU whenever available on the * platform. This flag is forced for user-space tasks. * * - T_SUSP causes the task to start in suspended mode. In such a * case, the thread will have to be explicitely resumed using the * rt_task_resume() service for its execution to actually begin. * * - T_CPU(cpuid) makes the new task affine to CPU # @b cpuid. CPU * identifiers range from 0 to RTHAL_NR_CPUS - 1 (inclusive). * * - T_JOINABLE (user-space only) allows another task to wait on the * termination of the new task. This implies that rt_task_join() is * actually called for this task to clean up any user-space located * resources after its termination. * * Passing T_FPU|T_CPU(1) in the @a mode parameter thus creates a task * with FPU support enabled and which will be affine to CPU #1. * * @return 0 is returned upon success. Otherwise: * * - -ENOMEM is returned if the system fails to get enough dynamic * memory from the global real-time heap in order to create or * register the task. * * - -EEXIST is returned if the @a name is already in use by some * registered object. * * - -EPERM is returned if this service was called from an * asynchronous context. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task * * Rescheduling: possible. */int rt_task_create (RT_TASK *task,		    const char *name,		    int stksize,		    int prio,		    int mode){    int err = 0, cpumask, cpu;    xnflags_t bflags;    spl_t s;    if (prio < T_LOPRIO || prio > T_HIPRIO)	return -EINVAL;    if (xnpod_asynch_p())	return -EPERM;    bflags = mode & (XNFPU|XNSHADOW|XNSHIELD|XNSUSP);    if (name)        {        if (!*name)	/* i.e. Anonymous object which must be accessible from	   user-space. */            xnobject_create_name(task->rname,sizeof(task->rname),task);        else            xnobject_copy_name(task->rname, name);        }    if (xnpod_init_thread(&task->thread_base,			  name,			  prio,			  bflags,			  stksize) != 0)	/* Assume this is the only possible failure. */	return -ENOMEM;    xnthread_set_magic(&task->thread_base,XENO_SKIN_MAGIC);    inith(&task->link);    task->suspend_depth = (bflags & XNSUSP) ? 1 : 0;    task->overrun = -1;    task->cstamp = ++__xeno_task_stamp;    task->safelock = 0;    xnsynch_init(&task->safesynch,XNSYNCH_FIFO);    xnarch_cpus_clear(task->affinity);    for (cpu = 0, cpumask = (mode >> 24) & 0xff;	 cpumask != 0 && cpu < 8; cpu++, cpumask >>= 1)	if (cpumask & 1)	    xnarch_cpu_set(cpu,task->affinity);#ifdef CONFIG_XENO_OPT_NATIVE_MPS    xnsynch_init(&task->mrecv,XNSYNCH_FIFO);    xnsynch_init(&task->msendq,XNSYNCH_PRIO|XNSYNCH_PIP);    xnsynch_set_owner(&task->msendq,&task->thread_base);    task->flowgen = 0;#endif /* CONFIG_XENO_OPT_NATIVE_MPS */    xnlock_get_irqsave(&nklock,s);    task->magic = XENO_TASK_MAGIC;    appendq(&__xeno_task_q,&task->link);    xnlock_put_irqrestore(&nklock,s);#ifdef CONFIG_XENO_OPT_REGISTRY    /* <!> Since xnregister_enter() may reschedule, only register       complete objects, so that the registry cannot return handles to       half-baked objects... */    if (name)	{	err = xnregistry_enter(task->rname,			       task,			       &xnthread_handle(&task->thread_base),			       NULL);        if (err)            rt_task_delete(task);	else if (!*name)	    /* /proc/xenomai/sched will dump no name for the anonymous	       task, but the registry still has a stable reference	       into the TCB to set up a handle for the task. */	    xnthread_clear_name(&task->thread_base);	}#endif /* CONFIG_XENO_OPT_REGISTRY */    return err;}/** * @fn int rt_task_start(RT_TASK *task,void (*entry)(void *cookie),void *cookie) * @brief Start a real-time task. * * Start a (newly) created task, scheduling it for the first * time. This call releases the target task from the dormant state. * * The TSTART hooks are called on behalf of the calling context (if * any, see rt_task_add_hook()). * * @param task The descriptor address of the affected task which must * have been previously created by the rt_task_create() service. * * @param entry The address of the task's body routine. In other * words, it is the task entry point. * * @param cookie A user-defined opaque cookie the real-time kernel * will pass to the emerging task as the sole argument of its entry * point. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a task is not a task descriptor. * * - -EIDRM is returned if @a task is a deleted task descriptor. * * - -EBUSY is returned if @a task is already started. * * - -EPERM is returned if this service was called from an * asynchronous context. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Kernel-based task * - User-space task * * Rescheduling: possible. */int rt_task_start (RT_TASK *task,		   void (*entry)(void *cookie),		   void *cookie){    int err = 0;    spl_t s;    if (xnpod_asynch_p())	return -EPERM;    xnlock_get_irqsave(&nklock,s);    task = xeno_h2obj_validate(task,XENO_TASK_MAGIC,RT_TASK);    if (!task)	{	err = xeno_handle_error(task,XENO_TASK_MAGIC,RT_TASK);	goto unlock_and_exit;	}    if (!xnthread_test_flags(&task->thread_base,XNDORMANT))	{	err = -EBUSY; /* Task already started. */	goto unlock_and_exit;	}    xnpod_start_thread(&task->thread_base,		       0,		       0,		       task->affinity,		       entry,		       cookie); unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return err;}/** * @fn int rt_task_suspend(RT_TASK *task) * @brief Suspend a real-time task. * * Forcibly suspend the execution of a task. This task will not be * eligible for scheduling until it is explicitly resumed by a call to * rt_task_resume(). In other words, the suspended state caused by a * call to rt_task_suspend() is cumulative with respect to the delayed * and blocked states caused by other services, and is managed * separately from them. * * A nesting count is maintained so that rt_task_suspend() and * rt_task_resume() must be used in pairs. * * @param task The descriptor address of the affected task. If @a task * is NULL, the current task is suspended. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a task is not a task descriptor. * * - -EPERM is returned if @a task is NULL but not called from a task * context, or this service was called from a context which cannot * sleep (e.g. interrupt, non-realtime or scheduler locked). * * - -EIDRM is returned if @a task is a deleted task descriptor. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine *   only if @a task is non-NULL. * * - Kernel-based task * - User-space task (switches to primary mode) * * Rescheduling: always if @a task is NULL. */int rt_task_suspend (RT_TASK *task){    int err = 0;    spl_t s;    if (!task)	{	if (!xnpod_primary_p())	    return -EPERM;	task = xeno_current_task();	}

⌨️ 快捷键说明

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