Look at the example:
static DECLARE_COMPLETION(my_thread_completion); static DECLARE_WAIT_QUEUE_HEAD(my_wait_queue); int request_to_end_thread = 0; static int my_thread(void *unused) { DECLARE_WAITQUEUE(wait, current); daemonize("my_thread"); add_wait_queue(&my_wait_queue, &wait); while (1) { //Request to opt out of the scheduler run queue. set_current_state(TASK_INTERRUPTIBLE); //asks the scheduler to choose and run a new task from its run queue. schedule(); /* The thread is put back into the scheduler run queue. This could only happend because of an event over the wait queue. */ if (request_to_end_thread) { break; } } //Bail out of the wait queue __set_current_state(TASK_RUNNING); remove_wait_queue(&my_wait_queue, &wait); //Atomically signal completion and exit complete_and_exit(&my_thread_completion, 0); } static int __init my_init(void) { kernel_thread(my_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD); } static void __exit my_release(void) { request_to_end_thread = 1; wake_up(&my_wait_queue);
//this function blocks until my_thread exit.
wait_for_completion(&my_thread_completion);
}
Note: There may be more then 1 waiter for the same completion, so the thread which notify its completion may use:
void complete_all(struct completion *c);
to notify all waiters.
No comments:
Post a Comment