static int kthread(void *_create) { struct kthread_create_info *create = _create; int (*threadfn)(void *data); void *data; int ret = -EINTR; /* Copy data: it's on kthread's stack */ threadfn = create->threadfn; data = create->data; /* OK, tell user we're spawned, wait for stop or wakeup */ __set_current_state(TASK_UNINTERRUPTIBLE); complete(&create->started); schedule(); if (!kthread_should_stop()) ret = threadfn(data); /* It might have exited on its own, w/o kthread_stop. Check. */ if (kthread_should_stop()) { kthread_stop_info.err = ret; complete(&kthread_stop_info.done); } return 0; }
static int kthread(void *_create) { /* Copy data: it's on kthread's stack */ struct kthread_create_info *create = _create; int (*threadfn)(void *data) = create->threadfn; void *data = create->data; struct kthread self; int ret; self.should_stop = 0; self.data = data; init_completion(&self.exited); current->vfork_done = &self.exited; /* OK, tell user we're spawned, wait for stop or wakeup */ __set_current_state(TASK_UNINTERRUPTIBLE); create->result = current; complete(&create->done); schedule(); ret = -EINTR; if (!self.should_stop) ret = threadfn(data); /* we can't just return, we must preserve "self" on stack */ do_exit(ret); }
static int kthread(void *_create) { /* */ struct kthread_create_info *create = _create; int (*threadfn)(void *data) = create->threadfn; void *data = create->data; struct kthread self; int ret; self.should_stop = 0; self.data = data; init_completion(&self.exited); current->vfork_done = &self.exited; /* */ __set_current_state(TASK_UNINTERRUPTIBLE); create->result = current; complete(&create->done); schedule(); ret = -EINTR; if (!self.should_stop) ret = threadfn(data); /* */ do_exit(ret); }
static int kthread(void *_create) { /* Copy data: it's on kthread's stack */ struct kthread_create_info *create = _create; int (*threadfn)(void *data) = create->threadfn; void *data = create->data; struct kthread self; int ret; self.flags = 0; self.data = data; init_completion(&self.exited); init_completion(&self.parked); current->vfork_done = &self.exited; /* OK, tell user we're spawned, wait for stop or wakeup */ __set_current_state(TASK_UNINTERRUPTIBLE); create->result = current; /* * Disable preemption so we enter TASK_UNINTERRUPTIBLE after * complete() instead of possibly being preempted. This speeds * up clients that do a kthread_bind() directly after * creation. */ preempt_disable(); complete(&create->done); preempt_enable_no_resched(); schedule(); ret = -EINTR; if (!test_bit(KTHREAD_SHOULD_STOP, &self.flags)) { __kthread_parkme(&self); ret = threadfn(data); } /* we can't just return, we must preserve "self" on stack */ do_exit(ret); }
static int kthread(void *_create) { struct kthread_create_info *create = _create; int (*threadfn)(void *data); void *data; sigset_t blocked; int ret = -EINTR; kthread_exit_files(); /* Copy data: it's on keventd's stack */ threadfn = create->threadfn; data = create->data; /* Block and flush all signals (in case we're not from keventd). */ sigfillset(&blocked); sigprocmask(SIG_BLOCK, &blocked, NULL); flush_signals(current); /* By default we can run anywhere, unlike keventd. */ set_cpus_allowed(current, CPU_MASK_ALL); /* OK, tell user we're spawned, wait for stop or wakeup */ __set_current_state(TASK_INTERRUPTIBLE); complete(&create->started); schedule(); if (!kthread_should_stop()) ret = threadfn(data); /* It might have exited on its own, w/o kthread_stop. Check. */ if (kthread_should_stop()) { kthread_stop_info.err = ret; complete(&kthread_stop_info.done); } return 0; }
static int kthread(void *_create) { /* Copy data: it's on kthread's stack */ struct kthread_create_info *create = _create; int (*threadfn)(void *data) = create->threadfn; void *data = create->data; struct completion *done; struct kthread self; int ret; self.flags = 0; self.data = data; init_completion(&self.exited); init_completion(&self.parked); current->vfork_done = &self.exited; /* If user was SIGKILLed, I release the structure. */ done = xchg(&create->done, NULL); if (!done) { kfree(create); do_exit(-EINTR); } /* OK, tell user we're spawned, wait for stop or wakeup */ __set_current_state(TASK_UNINTERRUPTIBLE); create->result = current; complete(done); schedule(); ret = -EINTR; if (!test_bit(KTHREAD_SHOULD_STOP, &self.flags)) { __kthread_parkme(&self); ret = threadfn(data); } /* we can't just return, we must preserve "self" on stack */ do_exit(ret); }
static int kthread(void *_create) { struct kthread_create_info *create = _create; int (*threadfn)(void *data); void *data; // printk("kthread: create %p\n", create); threadfn = create->threadfn; data = create->data; // printk("kthread: threadfn %p data %p\n", threadfn, data); lock_kernel(); daemonize(); reparent_to_init(); spin_lock_irq(¤t->sigmask_lock); sigfillset(¤t->blocked); recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); unlock_kernel(); set_current_state(TASK_INTERRUPTIBLE); complete(&create->started); // printk("kthread: about to call thread function\n"); if (!kthread_should_stop()) threadfn(data); // printk("kthread: thread function done\n"); if (kthread_should_stop()) complete(&kthread_stop_complete); return 0; }