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

📄 context.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
字号:
/* * linux/kernel/context.c * * Mechanism for running arbitrary tasks in process context * * dwmw2@redhat.com:		Genesis * * andrewm@uow.edu.au:		2.4.0-test12 *	- Child reaping *	- Support for tasks which re-add themselves *	- flush_scheduled_tasks. */#define __KERNEL_SYSCALLS__#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/unistd.h>#include <linux/signal.h>#include <linux/completion.h>static DECLARE_TASK_QUEUE(tq_context);static DECLARE_WAIT_QUEUE_HEAD(context_task_wq);static DECLARE_WAIT_QUEUE_HEAD(context_task_done);static int keventd_running;static struct task_struct *keventd_task;static int need_keventd(const char *who){	if (keventd_running == 0)		printk(KERN_ERR "%s(): keventd has not started\n", who);	return keventd_running;}	int current_is_keventd(void){	int ret = 0;	if (need_keventd(__FUNCTION__))		ret = (current == keventd_task);	return ret;}/** * schedule_task - schedule a function for subsequent execution in process context. * @task: pointer to a &tq_struct which defines the function to be scheduled. * * May be called from interrupt context.  The scheduled function is run at some * time in the near future by the keventd kernel thread.  If it can sleep, it * should be designed to do so for the minimum possible time, as it will be * stalling all other scheduled tasks. * * schedule_task() returns non-zero if the task was successfully scheduled. * If @task is already residing on a task queue then schedule_task() fails * to schedule your task and returns zero. */int schedule_task(struct tq_struct *task){	int ret;	need_keventd(__FUNCTION__);	ret = queue_task(task, &tq_context);	wake_up(&context_task_wq);	return ret;}static int context_thread(void *startup){	struct task_struct *curtask = current;	DECLARE_WAITQUEUE(wait, curtask);	struct k_sigaction sa;	daemonize();	strcpy(curtask->comm, "keventd");	keventd_running = 1;	keventd_task = curtask;	spin_lock_irq(&curtask->sigmask_lock);	siginitsetinv(&curtask->blocked, sigmask(SIGCHLD));	recalc_sigpending(curtask);	spin_unlock_irq(&curtask->sigmask_lock);	complete((struct completion *)startup);	/* Install a handler so SIGCLD is delivered */	sa.sa.sa_handler = SIG_IGN;	sa.sa.sa_flags = 0;	siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));	do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);	/*	 * If one of the functions on a task queue re-adds itself	 * to the task queue we call schedule() in state TASK_RUNNING	 */	for (;;) {		set_task_state(curtask, TASK_INTERRUPTIBLE);		add_wait_queue(&context_task_wq, &wait);		if (TQ_ACTIVE(tq_context))			set_task_state(curtask, TASK_RUNNING);		schedule();		remove_wait_queue(&context_task_wq, &wait);		run_task_queue(&tq_context);		wake_up(&context_task_done);		if (signal_pending(curtask)) {			while (waitpid(-1, (unsigned int *)0, __WALL|WNOHANG) > 0)				;			spin_lock_irq(&curtask->sigmask_lock);			flush_signals(curtask);			recalc_sigpending(curtask);			spin_unlock_irq(&curtask->sigmask_lock);		}	}}/** * flush_scheduled_tasks - ensure that any scheduled tasks have run to completion. * * Forces execution of the schedule_task() queue and blocks until its completion. * * If a kernel subsystem uses schedule_task() and wishes to flush any pending * tasks, it should use this function.  This is typically used in driver shutdown * handlers. * * The caller should hold no spinlocks and should hold no semaphores which could * cause the scheduled tasks to block. */static struct tq_struct dummy_task;void flush_scheduled_tasks(void){	int count;	DECLARE_WAITQUEUE(wait, current);	/*	 * Do it twice. It's possible, albeit highly unlikely, that	 * the caller queued a task immediately before calling us,	 * and that the eventd thread was already past the run_task_queue()	 * but not yet into wake_up(), so it woke us up before completing	 * the caller's queued task or our new dummy task.	 */	add_wait_queue(&context_task_done, &wait);	for (count = 0; count < 2; count++) {		set_current_state(TASK_UNINTERRUPTIBLE);		/* Queue a dummy task to make sure we get kicked */		schedule_task(&dummy_task);		/* Wait for it to complete */		schedule();	}	remove_wait_queue(&context_task_done, &wait);}	int start_context_thread(void){	static struct completion startup __initdata = COMPLETION_INITIALIZER(startup);	kernel_thread(context_thread, &startup, CLONE_FS | CLONE_FILES);	wait_for_completion(&startup);	return 0;}EXPORT_SYMBOL(schedule_task);EXPORT_SYMBOL(flush_scheduled_tasks);

⌨️ 快捷键说明

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