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

📄 task.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 5 页
字号:
 */int rt_task_notify (RT_TASK *task,		    rt_sigset_t signals){    int err = 0;    spl_t s;    if (!task)	{	if (!xnpod_primary_p())	    return -EPERM;	task = xeno_current_task();	}    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 (task->thread_base.asr == RT_HANDLER_NONE)	{	err = -ESRCH;	goto unlock_and_exit;	}    if (signals > 0)	{	task->thread_base.signals |= signals;	if (xnpod_current_thread() == &task->thread_base)	    xnpod_schedule();	} unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return err;}/** * @fn int rt_task_set_mode(int clrmask,int setmask,int *mode_r) * @brief Change task mode bits. * * Each Xenomai task has a set of internal bits determining various * operating conditions; the rt_task_set_mode() service allows to * alter three of them, respectively controlling: * * - whether the task locks the rescheduling procedure, * - whether the task undergoes a round-robin scheduling, * - whether the task blocks the delivery of signals. * * To this end, rt_task_set_mode() takes a bitmask of mode bits to * clear for disabling the corresponding modes, and another one to set * for enabling them. The mode bits which were previously in effect * can be returned upon request. * * The following bits can be part of the bitmask: * * - T_LOCK causes the current task to lock the scheduler. Clearing * this bit unlocks the scheduler. * * - T_RRB causes the current task to be marked as undergoing the * round-robin scheduling policy. If the task is already undergoing * the round-robin scheduling policy at the time this service is * called, the time quantum remains unchanged. * * - T_NOSIG disables the asynchronous signal delivery for the current * task. * * - T_SHIELD enables the interrupt shield for the current user-space * task. When engaged, the interrupt shield protects the Xenomai task * running in secondary mode from any preemption by the regular Linux * interrupt handlers, without delaying in any way the Xenomai interrupt * handling. The shield is operated on a per-task basis at each * context switch, depending on the setting of this flag. This flag is * set by default upon user-space task creation. This feature is only * available if the CONFIG_XENO_OPT_ISHIELD option has been enabled at * configuration time; otherwise, this flag is simply ignored. * * - When set, T_WARNSW causes the SIGXCPU signal to be sent to the * current user-space task whenever it switches to the secondary * mode. This feature is useful to detect unwanted migrations to the * Linux domain. * * - T_PRIMARY can be passed to switch the current user-space task to * primary mode (setmask |= T_PRIMARY), or secondary mode (clrmask |= * T_PRIMARY). Upon return from rt_task_set_mode(), the user-space * task will run into the specified domain. * * Normally, this service can only be called on behalf of a regular * real-time task, either running in kernel or user-space. However, as * a special exception, requests for setting/clearing the T_LOCK bit * from asynchronous contexts are silently dropped, and the call * returns successfully if no other mode bits have been * specified. This is consistent with the fact that Xenomai enforces a * scheduler lock until the outer interrupt handler has returned. * * @param clrmask A bitmask of mode bits to clear for the current * task, before @a setmask is applied. 0 is an acceptable value which * leads to a no-op. * * @param setmask A bitmask of mode bits to set for the current * task. 0 is an acceptable value which leads to a no-op. * * @param mode_r If non-NULL, @a mode_r must be a pointer to a memory * location which will be written upon success with the previous set * of active mode bits. If NULL, the previous set of active mode bits * will not be returned. * * @return 0 is returned upon success, or: * * - -EINVAL if either @a setmask or @a clrmask specifies invalid * bits. T_PRIMARY is invalid for kernel-based tasks. * * - -EPERM is returned if this service was not called from a * real-time task context. * * Environments: * * This service can be called from: * * - Kernel-based task * - User-space task * * Rescheduling: possible, if T_LOCK has been passed into @a clrmask * and the calling context is a task. */int rt_task_set_mode (int clrmask,		      int setmask,		      int *mode_r){    int mode;    if (xnpod_asynch_p())	{	clrmask &= ~T_LOCK;	setmask &= ~T_LOCK;	if (!clrmask && !setmask)	    return 0;	}    if (((clrmask|setmask) & ~(T_LOCK|T_RRB|T_NOSIG|T_SHIELD|T_WARNSW)) != 0)	return -EINVAL;    if (!xnpod_primary_p())	return -EPERM;    mode = xnpod_set_thread_mode(&xeno_current_task()->thread_base,				 clrmask,				 setmask);    if (mode_r)	*mode_r = mode;    if ((clrmask & ~setmask) & T_LOCK)	/* Reschedule if the scheduler has been unlocked. */	xnpod_schedule();    return 0;}/** * @fn RT_TASK *rt_task_self(void) * @brief Retrieve the current task. * * Return the current task descriptor address. * * @return The address of the caller's task descriptor is returned * upon success, or NULL if the calling context is asynchronous * (i.e. not a Xenomai task). * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * Those will cause a NULL return. * * - Kernel-based task * - User-space task * * Rescheduling: never. */RT_TASK *rt_task_self (void){    return !xnpod_primary_p() ? NULL : xeno_current_task();}/** * @fn int rt_task_slice(RT_TASK *task, RTIME quantum) * @brief Set a task's round-robin quantum. * * Set the time credit allotted to a task undergoing the round-robin * scheduling. As a side-effect, rt_task_slice() refills the current * quantum of the target task. * * @param task The descriptor address of the affected task. If @a task * is NULL, the current task is considered. * * @param quantum The round-robin quantum for the task expressed in * clock ticks (see note). * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a task is not a task descriptor, or if @a * quantum is zero. * * - -EPERM is returned if @a task is NULL but not called from a task * context. * * 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 * * Rescheduling: never. * * @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. */int rt_task_slice (RT_TASK *task, RTIME quantum){    int err = 0;    spl_t s;    if (!quantum)	return -EINVAL;    if (!task)	{	if (!xnpod_primary_p())	    return -EPERM;	task = xeno_current_task();	}    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;	}        xnthread_time_slice(&task->thread_base) = quantum;    xnthread_time_credit(&task->thread_base) = quantum; unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return err;}#ifdef CONFIG_XENO_OPT_NATIVE_MPS/** * @fn int rt_task_send(RT_TASK *task,RT_TASK_MCB *mcb_s,RT_TASK_MCB *mcb_r,RTIME timeout) * * @brief Send a message to a task. * * This service is part of the synchronous message passing support * available to Xenomai tasks. It allows the caller to send a * variable-sized message to another task, waiting for the remote to * receive the initial message by a call to rt_task_receive(), then * reply to it using rt_task_reply(). * * A basic message control block is used to store the location and * size of the data area to send or retrieve upon reply, in addition * to a user-defined operation code. * * @param task The descriptor address of the recipient task. * * @param mcb_s The address of the message control block referring to * the message to be sent. 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 operation 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 * operation code field by the rt_task_receive() service. * * @param mcb_r The address of an optional message control block * referring to the reply message area. If @a mcb_r is NULL and a * reply is sent back by the remote task, the reply message will be * discarded, and -ENOBUFS will be returned to the caller. When @a * mcb_r is valid, 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 reply data from 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 reply message, no data copy takes place and -ENOBUFS is * returned to the caller. See note. * * Upon return, mcb_r->opcode will contain the status code sent back * from the remote task using rt_task_reply(), or 0 if unspecified. * * @param timeout The number of clock ticks to wait for the remote * task to reply to the initial message (see note). Passing * TM_INFINITE causes the caller to block indefinitely until the * remote task eventually replies. Passing TM_NONBLOCK causes the * service to return immediately without waiting if the remote task is * not waiting for messages (i.e. if @a task is not currently blocked * on the rt_task_receive() service). * * @return A positive value is returned upon success, representing the * length (in bytes) of the reply message returned by the remote * task. 0 is a success status, meaning either that @a mcb_r was NULL * on entry, or that no actual message was passed to the remote call * to rt_task_reply(). Otherwise: * * - -ENOBUFS is returned if @a mcb_r does not point at a message area * large enough to collect the remote task's reply. This includes the * case where @a mcb_r is NULL on entry albeit the remote task * attempts to send a reply message. * * - -EWOULDBLOCK is returned if @a timeout is equal to TM_NONBLOCK * and @a task is not currently blocked on the rt_task_receive() * service. * * - -EIDRM is returned if @a task has been deleted while waiting for * a reply. * * - -EINTR is returned if rt_task_unblock() has been called for the * caller before any reply was available. * * - -EPERM is returned if this service should block, but 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 * both the sent and the reply data if this cumulated size exceeds a * certain amount; the threshold before allocation is currently set to * 64 bytes. */ssize_t rt_task_send (RT_TASK *task,		      RT_TASK_MCB *mcb_s,		      RT_TASK_MCB *mcb_r,		      RTIME timeout){    RT_TASK *sender;    size_t rsize;    ssize_t err;    spl_t s;    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 (timeout == TM_NONBLOCK && xnsynch_nsleepers(&task->mrecv) == 0)	{	/* Can't block and no receiver pending; just bail out. */	err = -EWOULDBLOCK;	goto unlock_and_exit;	}    if (xnpod_unblockable_p())	{	err = -EPERM;	goto unlock_and_exit;	}    sender = xeno_current_task();    /* First, setup the send control block. Compute the flow       identifier, making sure that we won't draw a null or negative       value. */    if (++task->flowgen < 0)	task->flowgen = 1;    mcb_s->flowid = task->flowgen;    sender->wait_args.mps.mcb_s = *mcb_s;    /* Then, setup the reply control block. */    if (mcb_r)	sender->wait_args.mps.mcb_r = *mcb_r;    else	sender->wait_args.mps.mcb_r.size = 0;    /* Wake up the receiver if it is currently waiting for a message,       then sleep on the send queue, waiting for the remote       reply. xnsynch_sleep_on() will reschedule as needed. */    xnsynch_flush(&task->mrecv,0);    /* Since the receiver is perpetually marked as the current owner       of its own send queue which has been declared as a PIP-enabled       object, it will inherit the priority of the sender in the case       required by the priority inheritance protocol       (i.e. prio(sender) > prio(receiver)). */    xnsynch_sleep_on(&task->msendq,timeout);

⌨️ 快捷键说明

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