📄 task.c
字号:
*/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 + -