exit: Implement kthread_exit
[ Upstream commitbbda86e988
] The way the per task_struct exit_code is used by kernel threads is not quite compatible how it is used by userspace applications. The low byte of the userspace exit_code value encodes the exit signal. While kthreads just use the value as an int holding ordinary kernel function exit status like -EPERM. Add kthread_exit to clearly separate the two kinds of uses. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Stable-dep-of:ca3574bd65
("exit: Rename module_put_and_exit to module_put_and_kthread_exit") Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
Родитель
de7e2adfc7
Коммит
dd66630966
|
@ -95,6 +95,7 @@ void *kthread_probe_data(struct task_struct *k);
|
||||||
int kthread_park(struct task_struct *k);
|
int kthread_park(struct task_struct *k);
|
||||||
void kthread_unpark(struct task_struct *k);
|
void kthread_unpark(struct task_struct *k);
|
||||||
void kthread_parkme(void);
|
void kthread_parkme(void);
|
||||||
|
void kthread_exit(long result) __noreturn;
|
||||||
|
|
||||||
int kthreadd(void *unused);
|
int kthreadd(void *unused);
|
||||||
extern struct task_struct *kthreadd_task;
|
extern struct task_struct *kthreadd_task;
|
||||||
|
|
|
@ -268,6 +268,21 @@ void kthread_parkme(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kthread_parkme);
|
EXPORT_SYMBOL_GPL(kthread_parkme);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kthread_exit - Cause the current kthread return @result to kthread_stop().
|
||||||
|
* @result: The integer value to return to kthread_stop().
|
||||||
|
*
|
||||||
|
* While kthread_exit can be called directly, it exists so that
|
||||||
|
* functions which do some additional work in non-modular code such as
|
||||||
|
* module_put_and_kthread_exit can be implemented.
|
||||||
|
*
|
||||||
|
* Does not return.
|
||||||
|
*/
|
||||||
|
void __noreturn kthread_exit(long result)
|
||||||
|
{
|
||||||
|
do_exit(result);
|
||||||
|
}
|
||||||
|
|
||||||
static int kthread(void *_create)
|
static int kthread(void *_create)
|
||||||
{
|
{
|
||||||
/* Copy data: it's on kthread's stack */
|
/* Copy data: it's on kthread's stack */
|
||||||
|
@ -285,13 +300,13 @@ static int kthread(void *_create)
|
||||||
done = xchg(&create->done, NULL);
|
done = xchg(&create->done, NULL);
|
||||||
if (!done) {
|
if (!done) {
|
||||||
kfree(create);
|
kfree(create);
|
||||||
do_exit(-EINTR);
|
kthread_exit(-EINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self) {
|
if (!self) {
|
||||||
create->result = ERR_PTR(-ENOMEM);
|
create->result = ERR_PTR(-ENOMEM);
|
||||||
complete(done);
|
complete(done);
|
||||||
do_exit(-ENOMEM);
|
kthread_exit(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
self->threadfn = threadfn;
|
self->threadfn = threadfn;
|
||||||
|
@ -318,7 +333,7 @@ static int kthread(void *_create)
|
||||||
__kthread_parkme(self);
|
__kthread_parkme(self);
|
||||||
ret = threadfn(data);
|
ret = threadfn(data);
|
||||||
}
|
}
|
||||||
do_exit(ret);
|
kthread_exit(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called from kernel_clone() to get node information for about to be created task */
|
/* called from kernel_clone() to get node information for about to be created task */
|
||||||
|
@ -628,7 +643,7 @@ EXPORT_SYMBOL_GPL(kthread_park);
|
||||||
* instead of calling wake_up_process(): the thread will exit without
|
* instead of calling wake_up_process(): the thread will exit without
|
||||||
* calling threadfn().
|
* calling threadfn().
|
||||||
*
|
*
|
||||||
* If threadfn() may call do_exit() itself, the caller must ensure
|
* If threadfn() may call kthread_exit() itself, the caller must ensure
|
||||||
* task_struct can't go away.
|
* task_struct can't go away.
|
||||||
*
|
*
|
||||||
* Returns the result of threadfn(), or %-EINTR if wake_up_process()
|
* Returns the result of threadfn(), or %-EINTR if wake_up_process()
|
||||||
|
|
|
@ -169,6 +169,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
|
||||||
"panic",
|
"panic",
|
||||||
"do_exit",
|
"do_exit",
|
||||||
"do_task_dead",
|
"do_task_dead",
|
||||||
|
"kthread_exit",
|
||||||
"make_task_dead",
|
"make_task_dead",
|
||||||
"__module_put_and_exit",
|
"__module_put_and_exit",
|
||||||
"complete_and_exit",
|
"complete_and_exit",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче