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

📄 common.c

📁 rtai-3.1-test3的源代码(Real-Time Application Interface )
💻 C
📖 第 1 页 / 共 3 页
字号:
/**  * @ingroup lxrt * @file * Common scheduling function  * @author Paolo Mantegazza * * This file is part of the RTAI project. * * @note Copyright &copy; 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it> * * 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. */#include <rtai_schedcore.h>#include <rtai_registry.h>#include <linux/module.h>/* ++++++++++++++++++++++++ COMMON FUNCTIONALITIES ++++++++++++++++++++++++++ *//* +++++++++++++++++++++++++ PRIORITY MANAGEMENT ++++++++++++++++++++++++++++ */void rt_set_sched_policy(RT_TASK *task, int policy, int rr_quantum_ns){	if ((task->policy = policy ? 1 : 0)) {		task->rr_quantum = nano2count_cpuid(rr_quantum_ns, task->runnable_on_cpus);		if ((task->rr_quantum & 0xF0000000) || !task->rr_quantum) {#ifdef CONFIG_SMP			task->rr_quantum = sqilter ? rt_smp_times[task->runnable_on_cpus].linux_tick : rt_times.linux_tick;#else			task->rr_quantum = rt_times.linux_tick;#endif		}		task->rr_remaining = task->rr_quantum;		task->yield_time = 0;	}}/** * @anchor rt_get_prio * @brief Check a task priority. *  * rt_get_prio returns the base priority of task @e task. * * Recall that a task has a base native priority, assigned at its * birth or by @ref rt_change_prio(), and an actual, inherited, * priority. They can be different because of priority inheritance. * * @param task is the affected task. * * @return rt_get_prio returns the priority of task @e task. * * @note To be used only with RTAI24.x.xx. */int rt_get_prio(RT_TASK *task){	if (task->magic != RT_TASK_MAGIC) {		return -EINVAL;	}	return task->base_priority;}/** * @anchor rt_get_inher_prio * @brief Check a task priority. *  * rt_get_prio returns the base priority task @e task has inherited * from other tasks, either blocked on resources owned by or waiting * to pass a message to task @e task. * * Recall that a task has a base native priority, assigned at its * birth or by @ref rt_change_prio(), and an actual, inherited, * priority. They can be different because of priority inheritance. * * @param task is the affected task. * * @return rt_get_inher_prio returns the priority of task @e task. * * @note To be used only with RTAI24.x.xx. */int rt_get_inher_prio(RT_TASK *task){	if (task->magic != RT_TASK_MAGIC) {		return -EINVAL;	}	return task->base_priority;}/** * @anchor rt_change_prio * @brief Change a task priority. *  * rt_change_prio changes the base priority of task @e task to @e * prio.  * * Recall that a task has a base native priority, assigned at its * birth or by @ref rt_change_prio(), and an actual, inherited, * priority. They can be different because of priority inheritance. * * @param task is the affected task. * * @param priority is the new priority, it can range within 0 < prio <  * RT_SCHED_LOWEST_PRIORITY.  * * @return rt_change_prio returns the base priority task @e task had * before the change. * * @note To be used only with RTAI24.x.xx (FIXME). */int rt_change_prio(RT_TASK *task, int priority){	unsigned long flags;	int prio;	if (task->magic != RT_TASK_MAGIC || priority < 0) {		return -EINVAL;	}	prio = task->base_priority;	flags = rt_global_save_flags_and_cli();	if ((task->base_priority = priority) < task->priority) {		unsigned long schedmap;		QUEUE *q;		schedmap = 0;		do {			task->priority = priority;			if (task->state == RT_SCHED_READY) {				(task->rprev)->rnext = task->rnext;				(task->rnext)->rprev = task->rprev;				enq_ready_task(task);#ifdef CONFIG_SMP				set_bit(task->runnable_on_cpus & 0x1F, &schedmap);#else				schedmap = 1;#endif			} else if ((q = task->blocked_on) && !((task->state & RT_SCHED_SEMAPHORE) && ((SEM *)q)->qtype)) {				(task->queue.prev)->next = task->queue.next;				(task->queue.next)->prev = task->queue.prev;				while ((q = q->next) != task->blocked_on && (q->task)->priority <= priority);				q->prev = (task->queue.prev = q->prev)->next  = &(task->queue);				task->queue.next = q;#ifdef CONFIG_SMP				set_bit(task->runnable_on_cpus & 0x1F, &schedmap);#else				schedmap = 1;#endif			}		} while ((task = task->prio_passed_to) && task->priority > priority);		if (schedmap) {#ifdef CONFIG_SMP			if (test_and_clear_bit(hard_cpu_id(), &schedmap)) {				RT_SCHEDULE_MAP_BOTH(schedmap);			} else {				RT_SCHEDULE_MAP(schedmap);			}#else			rt_schedule();#endif		}	}	rt_global_restore_flags(flags);	return prio;}/* +++++++++++++++++++++ TASK RELATED SCHEDULER SERVICES ++++++++++++++++++++ *//** * @anchor rt_whoami * @brief Get the task pointer of the current task. * * Calling rt_whoami from a task can get a pointer to its own task * structure. *  * @return The pointer to the current task. */RT_TASK *rt_whoami(void){	return _rt_whoami();}/** * @anchor rt_task_yield * Yield the current task. * * @ref rt_task_yield() stops the current task and takes it at the end * of the list of ready tasks having its same priority. The scheduler * makes the next ready task of the same priority active. * * Recall that RTAI schedulers allow only higher priority tasks to * preempt the execution of lower priority ones. So equal priority * tasks cannot preempt each other and @ref rt_task_yield() should be * used if a user needs a cooperative time slicing among equal * priority tasks. The implementation of the related policy is wholly * in the hand of the user. It is believed that time slicing is too * much an overhead for the most demanding real time applications, so * it is left up to you. */void rt_task_yield(void){	RT_TASK *rt_current, *task;	unsigned long flags;	flags = rt_global_save_flags_and_cli();	task = (rt_current = RT_CURRENT)->rnext;	while (rt_current->priority == task->priority) {		task = task->rnext;	}	if (task != rt_current->rnext) {		(rt_current->rprev)->rnext = rt_current->rnext;		(rt_current->rnext)->rprev = rt_current->rprev;		task->rprev = (rt_current->rprev = task->rprev)->rnext = rt_current;		rt_current->rnext = task;		rt_schedule();	}	rt_global_restore_flags(flags);}/** * @anchor rt_task_suspend * rt_task_suspend suspends execution of the task task. * * It will not be executed until a call to @ref rt_task_resume() or * @ref rt_task_make_periodic() is made. No account is made for * multiple suspends, i.e. a multiply suspended task is made ready as * soon as it is rt_task_resumed, thus immediately resuming its * execution if it is the highest in priority. * * @param task pointer to a task structure. * * @return 0 on success. A negative value on failure as described below: * - @b EINVAL: task does not refer to a valid task. * * @note the new RTAI 24.1.xx (FIXME) development releases take into * account multiple suspend and require as many @ref rt_task_resume() * as the rt_task_suspends placed on a task. */int rt_task_suspend(RT_TASK *task){	unsigned long flags;	if (!task) {		task = RT_CURRENT;	} else if (task->magic != RT_TASK_MAGIC) {		return -EINVAL;	}	flags = rt_global_save_flags_and_cli();	if (!task->suspdepth++ && !task->owndres) {		rem_ready_task(task);		task->state |= RT_SCHED_SUSPENDED;		if (task == RT_CURRENT) {			rt_schedule();		}	}	rt_global_restore_flags(flags);	return 0;}/** * @anchor rt_task_resume * Resume a task. * * rt_task_resume resumes execution of the task @e task previously * suspended by @ref rt_task_suspend(), or makes a newly created task * ready to run, if it makes the task ready. Since no account is made * for multiple suspend rt_task_resume unconditionally resumes any * task it makes ready. * * @param task pointer to a task structure. * * @return 0 on success. A negative value on failure as described below: * - @b EINVAL: task does not refer to a valid task. * * @note the new RTAI 24.1.xx (FIXME) development releases take into *       account multiple suspend and require as many rt_task_resumes *	 as the rt_task_suspends placed on a task. */int rt_task_resume(RT_TASK *task){	unsigned long flags;	if (task->magic != RT_TASK_MAGIC) {		return -EINVAL;	}	flags = rt_global_save_flags_and_cli();	if (!(--task->suspdepth)) {		rem_timed_task(task);		if (((task->state &= ~RT_SCHED_SUSPENDED) & ~RT_SCHED_DELAYED) == RT_SCHED_READY) {			enq_ready_task(task);			RT_SCHEDULE(task, hard_cpu_id());		}	}	rt_global_restore_flags(flags);	return 0;}/** * @anchor rt_get_task_state * Query task state * * rt_get_task_state returns the state of a real time task. * * @param task is a pointer to the task structure. * * Task state is formed by the bitwise OR of one or more of the * following flags: * * @retval READY Task @e task is ready to run (i.e. unblocked). * Note that on a UniProcessor machine the currently running task is * just in READY state, while on MultiProcessors can be (READY | * RUNNING), see below.  * @retval SUSPENDED Task @e task blocked waiting for a resume. * @retval DELAYED Task @e task blocked waiting for its next running * period or expiration of a timeout. * @retval SEMAPHORE Task @e task blocked on a semaphore, waiting for * the semaphore to be signaled. * @retval SEND Task @e task blocked on sending a message, receiver * was not in RECEIVE state. * @retval RECEIVE Task @e task blocked waiting for incoming messages, * sends or rpcs.  * @retval RPC Task @e task blocked on a Remote Procedure Call, * receiver was not in RECEIVE state. * @retval RETURN Task @e task blocked waiting for a return from a * Remote Procedure Call, receiver got the RPC but has not replied * yet.  * @retval RUNNING Task @e task is running, used only for SMP * schedulers.  * * The returned task state is just an approximate information. Timer * and other hardware interrupts may cause a change in the state of * the queried task before the caller could evaluate the returned * value. Caller should disable interrupts if it wants reliable info * about an other task.  rt_get_task_state does not perform any check * on pointer task. */int rt_get_task_state(RT_TASK *task){	return task->state;}/** * @anchor rt_linux_use_fpu * @brief Set indication of FPU usage. * * rt_linux_use_fpu informs the scheduler that floating point * arithmetic operations will be used also by foreground Linux * processes, i.e. the Linux kernel itself (unlikely) and any of its * processes.  * * @param use_fpu_flag If this parameter has a nonzero value, the * Floating Point Unit (FPU) context is also switched when @e task or * the kernel becomes active. * This makes task switching slower, negligibly, on all 32 bits CPUs * but 386s and the oldest 486s.  * This flag can be set also by rt_task_init when the real time task * is created. With UP and MUP schedulers care is taken to avoid * useless saves/ restores of the FPU environment.  * Under SMP tasks can be moved from CPU to CPU so saves/restores for * tasks using the FPU are always carried out.  * Note that by default Linux has this flag cleared. Beside by using * rt_linux_use_fpu you can change the Linux FPU flag when you insmod * any RTAI scheduler module by setting the LinuxFpu command line * parameter of the rtai_sched module itself. * * @return 0 on success. A negative value on failure as described below: * - @b EINVAL: task does not refer to a valid task. * * See also: @ref rt_linux_use_fpu(). */void rt_linux_use_fpu(int use_fpu_flag){	int cpuid;	for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) {		rt_linux_task.uses_fpu = use_fpu_flag ? 1 : 0;	}}/** * @anchor rt_task_use_fpu * @brief  * * rt_task_use_fpu informs the scheduler that floating point * arithmetic operations will be used by the real time task @e task. * * @param task is a pointer to the real time task. *  * @param use_fpu_flag If this parameter has a nonzero value, the * Floating Point Unit (FPU) context is also switched when @e task or * the kernel becomes active. * This makes task switching slower, negligibly, on all 32 bits CPUs * but 386s and the oldest 486s. * This flag can be set also by @ref rt_task_init() when the real time * task is created. With UP and MUP schedulers care is taken to avoid * useless saves/restores of the FPU environment. * Under SMP tasks can be moved from CPU to CPU so saves/restores for * tasks using the FPU are always carried out.  * * @return 0 on success. A negative value on failure as described below: * - @b EINVAL: task does not refer to a valid task. * * See also: @ref rt_linux_use_fpu(). */int rt_task_use_fpu(RT_TASK *task, int use_fpu_flag){	if (task->magic != RT_TASK_MAGIC) {		return -EINVAL;	}	task->uses_fpu = use_fpu_flag ? 1 : 0;	return 0;}/** * @anchor rt_task_signal_handler * @brief Set the signal handler of a task. * * rt_task_signal_handler installs, or changes, the signal function * of a real time task. * * @param task is a pointer to the real time task. * * @param handler is the entry point of the signal function. * * A signal handler function can be set also when the task is newly * created with @ref rt_task_init(). The signal handler is a function * called within the task environment and with interrupts disabled, * when the task becomes the current running task after a context * switch, except at its very first scheduling. It allows you to * implement whatever signal management policy you think useful, and * many other things as well (FIXME). * * @return 0 on success.A negative value on failure as described below: * - @b EINVAL: task does not refer to a valid task. */int rt_task_signal_handler(RT_TASK *task, void (*handler)(void)){	if (task->magic != RT_TASK_MAGIC) {		return -EINVAL;	}	task->signal = handler;	return 0;}/* ++++++++++++++++++++++++++++ MEASURING TIME ++++++++++++++++++++++++++++++ */void rt_gettimeorig(RTIME time_orig[]){	unsigned long flags;	struct timeval tv;	hard_save_flags_and_cli(flags);	do_gettimeofday(&tv);	time_orig[0] = rdtsc();	hard_restore_flags(flags);	time_orig[0] = tv.tv_sec*(long long)tuned.cpu_freq + llimd(tv.tv_usec, tuned.cpu_freq, 1000000) - time_orig[0];	time_orig[1] = llimd(time_orig[0], 1000000000, tuned.cpu_freq);}/* +++++++++++++++++++++++++++ CONTROLLING TIME ++++++++++++++++++++++++++++++ *//** * @anchor rt_task_make_periodic_relative_ns * Make a task run periodically. * * rt_task_make_periodic_relative_ns mark the task @e task, previously

⌨️ 快捷键说明

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