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

📄 task.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (xnthread_test_flags(&sender->thread_base,XNRMID))	err = -EIDRM; /* Receiver deleted while pending. */    else if (xnthread_test_flags(&sender->thread_base,XNTIMEO))	err = -ETIMEDOUT; /* Timeout.*/    else if (xnthread_test_flags(&sender->thread_base,XNBREAK))	err = -EINTR; /* Unblocked.*/    else	{	rsize = sender->wait_args.mps.mcb_r.size;	if (rsize > 0)	    {	    /* Ok, the message has been processed and answered by the	       remote, and a memory address is available to pass the	       reply back to our caller: let's do it. Make sure we	       have enough buffer space to perform the entire copy. */	    if (mcb_r != NULL && rsize <= mcb_r->size)		{		memcpy(mcb_r->data,sender->wait_args.mps.mcb_r.data,rsize);		err = (ssize_t)rsize;		}	    else		err = -ENOBUFS;	    }	else	    err = 0; /* i.e. message processed, no reply expected or sent. */	/* The status code is considered meaningful whether there is	   some actual reply data or not; recycle the opcode field to	   return it. */	if (mcb_r)	    {	    mcb_r->opcode = sender->wait_args.mps.mcb_r.opcode;	    mcb_r->size = rsize;	    }	} unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return err;}/** * @fn int rt_task_receive(RT_TASK_MCB *mcb_r,RTIME timeout) * @brief Receive a message from a task. * * This service is part of the synchronous message passing support * available to Xenomai tasks. It allows the caller to receive a * variable-sized message sent from another task using the * rt_task_send() service. The sending task is blocked until the * caller invokes rt_task_reply() to finish the transaction. * * A basic message control block is used to store the location and * size of the data area to receive from the sender, in addition to a * user-defined operation code. * * @param mcb_r The address of a message control block referring to * the receive message area. The fields from this control block should * be set as follows: * * - mcb_r->data should contain the address of a buffer large enough * to collect the data sent by the remote task; * * - mcb_r->size should contain the size in bytes of the buffer space * pointed at by mcb_r->data. If mcb_r->size is lower than the actual * size of the received message, no data copy takes place and -ENOBUFS * is returned to the caller. See note. * * Upon return, mcb_r->opcode will contain the operation code sent * from the remote task using rt_task_send(). * * @param timeout The number of clock ticks to wait for receiving a * message (see note). Passing TM_INFINITE causes the caller to block * indefinitely until a remote task eventually sends a message. * Passing TM_NONBLOCK causes the service to return immediately * without waiting if no remote task is currently waiting for sending * a message. * * @return A strictly positive value is returned upon success, * representing a flow identifier for the opening transaction; this * token should be passed to rt_task_reply(), in order to send back a * reply to and unblock the remote task appropriately. Otherwise: * * - -ENOBUFS is returned if @a mcb_r does not point at a message area * large enough to collect the remote task's message. * * - -EWOULDBLOCK is returned if @a timeout is equal to TM_NONBLOCK * and no remote task is currently waiting for sending a message to * the caller. * * - -ETIMEDOUT is returned if no message was received within the @a * timeout. * * - -EINTR is returned if rt_task_unblock() has been called for the * caller before any message was available. * * - -EPERM is returned if this service was called from a context * which cannot sleep (e.g. interrupt, non-realtime or scheduler * locked). * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (switches to primary mode) * * Rescheduling: Always. * * @note This service is sensitive to the current operation mode of * the system timer, as defined by the rt_timer_start() service. In * periodic mode, clock ticks are interpreted as periodic jiffies. In * oneshot mode, clock ticks are interpreted as nanoseconds. * * @note When called from a user-space task, this service may need to * allocate some temporary buffer space from the system heap to hold * the received data if the size of the latter exceeds a certain * amount; the threshold before allocation is currently set to 64 * bytes. */int rt_task_receive (RT_TASK_MCB *mcb_r,		     RTIME timeout){    RT_TASK *receiver, *sender;    xnpholder_t *holder;    size_t rsize;    int err;    spl_t s;    if (!xnpod_primary_p())	return -EPERM;    receiver = xeno_current_task();    xnlock_get_irqsave(&nklock,s);    /* Fetch the first available message, but don't wake up the sender       until our caller invokes rt_task_reply(). IOW,       rt_task_receive() will fetch back the exact same message until       rt_task_reply() is called to release the heading sender. */    holder = getheadpq(xnsynch_wait_queue(&receiver->msendq));    if (holder)	goto pull_message;    if (timeout == TM_NONBLOCK)	{	err = -EWOULDBLOCK;	goto unlock_and_exit;	}    if (xnpod_unblockable_p())	{	err = -EPERM;	goto unlock_and_exit;	}    /* Wait on our receive slot for some sender to enqueue itself in       our send queue. */    xnsynch_sleep_on(&receiver->mrecv,timeout);    /* XNRMID cannot happen, since well, the current task would be the       deleted object, so... */    if (xnthread_test_flags(&receiver->thread_base,XNTIMEO))	{	err = -ETIMEDOUT; /* Timeout.*/	goto unlock_and_exit;	}    else if (xnthread_test_flags(&receiver->thread_base,XNBREAK))	{	err = -EINTR; /* Unblocked.*/	goto unlock_and_exit;	}    holder = getheadpq(xnsynch_wait_queue(&receiver->msendq));    /* There must be a valid holder since we waited for it. */ pull_message:    sender = thread2rtask(link2thread(holder,plink));    rsize = sender->wait_args.mps.mcb_s.size;    if (rsize <= mcb_r->size)	{	if (rsize > 0)	    memcpy(mcb_r->data,sender->wait_args.mps.mcb_s.data,rsize);	/* The flow identifier can't be either null or negative. */	err = sender->wait_args.mps.mcb_s.flowid;	}    else	err = -ENOBUFS;    mcb_r->opcode = sender->wait_args.mps.mcb_s.opcode;    mcb_r->size = rsize; unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return err;}/** * @fn int rt_task_reply(int flowid,RT_TASK_MCB *mcb_s) * @brief Reply to a task. * * This service is part of the synchronous message passing support * available to Xenomai tasks. It allows the caller to send back a * variable-sized message to the sender task, once the initial message * from this task has been pulled using rt_task_receive() and * processed. As a consequence of this call, the remote task will be * unblocked from the rt_task_send() service. * * A basic message control block is used to store the location and * size of the data area to send back, in addition to a user-defined * status code. * * @param flowid The flow identifier returned by a previous call to * rt_task_receive() which uniquely identifies the current * transaction. * * @param mcb_s The address of an optional message control block * referring to the message to be sent back. If @a mcb_s is NULL, the * sender will be unblocked without getting any reply data. When @a * mcb_s is valid, the fields from this control block should be set as * follows: * * - mcb_s->data should contain the address of the payload data to * send to the remote task. * * - mcb_s->size should contain the size in bytes of the payload data * pointed at by mcb_s->data. 0 is a legitimate value, and indicates * that no payload data will be transferred. In the latter case, * mcb_s->data will be ignored. See note. * * - mcb_s->opcode is an opaque status code carried during the message * transfer the caller can fill with any appropriate value. It will be * made available "as is" to the remote task into the status code * field by the rt_task_send() service. If @a mcb_s is NULL, 0 will be * returned to the initial sender into the status code field. * * @return O is returned upon success. Otherwise: * * - -ENXIO is returned if @a flowid does not match the expected * identifier returned from the latest call of the current task to * rt_task_receive(), or if the remote task stopped waiting for the * reply in the meantime (e.g. the initial sender could have been * deleted or forcibly unblocked). * * - -EPERM is returned if this service was called from an invalid * context (e.g. interrupt, or non-primary). * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task (switches to primary mode) * * Rescheduling: Always. * * @note When called from a user-space task, this service may need to * allocate some temporary buffer space from the system heap to hold * the reply data if the size of the latter exceeds a certain amount; * the threshold before allocation is currently set to 64 bytes. */int rt_task_reply (int flowid, RT_TASK_MCB *mcb_s){    RT_TASK *sender, *receiver;    xnpholder_t *holder;    size_t rsize;    int err;    spl_t s;    if (!xnpod_primary_p())	return -EPERM;    sender = xeno_current_task();    xnlock_get_irqsave(&nklock,s);    for (holder = getheadpq(xnsynch_wait_queue(&sender->msendq)), receiver = NULL;	 holder != NULL;	 holder = nextpq(xnsynch_wait_queue(&sender->msendq),holder))	{	receiver = thread2rtask(link2thread(holder,plink));	/* Check the flow identifier, just in case the sender has	   vanished away while we were processing its last	   message. Each sent message carries a distinct flow	   identifier from other senders wrt to a given receiver. */	if (receiver->wait_args.mps.mcb_s.flowid == flowid)	    {	    /* Note that the following will cause the receiver to be	       unblocked without transferring the ownership of the	       msendq object, since we want the sender to keep it. */	    xnpod_resume_thread(&receiver->thread_base,XNPEND);	    break;	    }	}    if (!receiver)	{	err = -ENXIO;	goto unlock_and_exit;	}    /* Copy the reply data to a location where the receiver can find       it. */    rsize = mcb_s ? mcb_s->size : 0;    err = 0;    if (receiver->wait_args.mps.mcb_r.size >= rsize)	{	/* Sending back a NULL or zero-length reply is perfectly	   valid; it just means to unblock the initial sender without	   passing it back any reply data. */	if (rsize > 0)	    memcpy(receiver->wait_args.mps.mcb_r.data,mcb_s->data,rsize);	}    else	/* The receiver will get the same error code. Falldown	   through the rescheduling is wanted. */	err = -ENOBUFS;    /* Copy back the actual size of the reply data, */    receiver->wait_args.mps.mcb_r.size = rsize;    /* And the status code. */    receiver->wait_args.mps.mcb_r.opcode = mcb_s ? mcb_s->opcode : 0;    /* That's it, we just need to start the rescheduling procedure       now. */    xnpod_schedule(); unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return err;}#endif /* CONFIG_XENO_OPT_NATIVE_MPS *//** * @fn int rt_task_spawn(RT_TASK *task,const char *name,int stksize,int prio,int mode,void (*entry)(void *cookie),void *cookie) * @brief Spawn a new real-time task. * * Creates and immediately starts a real-time task, either running in * a kernel module or in user-space depending on the caller's * context. This service is a simple shorthand for rt_task_create() * followed by a call to rt_task_start(). * * @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. * * @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). * * 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. * * @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: * * - -ENOMEM is returned if the system fails to get enough dynamic * memory from the global real-time heap in order to create the new * task's stack space 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. *//** * @fn int rt_task_shadow(RT_TASK *task,const char *name,int prio,int mode) * @brief Turns the current Linux task into a native Xenomai task. * * Creates a real-time task running in the context of the calling * regular Linux task in user-space. * * @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 current context is switched to primary execution mode and * returns immediately, unless T_SUSP has been passed in the @a mode * parameter. * * @param name An ASCII string standing for the symbolic name of the * task. When non-NULL and non-empty, this string

⌨️ 快捷键说明

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