File Index
Files and directories
Sign in
FILE

try-catch.c

File preview with syntax highlighting.

linux-6.19.14/lib/kunit/try-catch.c C
 1// SPDX-License-Identifier: GPL-2.0
 2/*
 3 * An API to allow a function, that may fail, to be executed, and recover in a
 4 * controlled manner.
 5 *
 6 * Copyright (C) 2019, Google LLC.
 7 * Author: Brendan Higgins <brendanhiggins@google.com>
 8 */
 9
10#include <kunit/test.h>
11#include <linux/completion.h>
12#include <linux/kernel.h>
13#include <linux/kthread.h>
14#include <linux/sched/task.h>
15
16#include "try-catch-impl.h"
17
18void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
19{
20	try_catch->try_result = -EFAULT;
21	kthread_exit(0);
22}
23EXPORT_SYMBOL_GPL(kunit_try_catch_throw);
24
25static int kunit_generic_run_threadfn_adapter(void *data)
26{
27	struct kunit_try_catch *try_catch = data;
28
29	try_catch->try_result = -EINTR;
30	try_catch->try(try_catch->context);
31	if (try_catch->try_result == -EINTR)
32		try_catch->try_result = 0;
33
34	return 0;
35}
36
37void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
38{
39	struct kunit *test = try_catch->test;
40	struct task_struct *task_struct;
41	struct completion *task_done;
42	int exit_code, time_remaining;
43
44	try_catch->context = context;
45	try_catch->try_result = 0;
46	task_struct = kthread_create(kunit_generic_run_threadfn_adapter,
47				     try_catch, "kunit_try_catch_thread");
48	if (IS_ERR(task_struct)) {
49		try_catch->try_result = PTR_ERR(task_struct);
50		try_catch->catch(try_catch->context);
51		return;
52	}
53	get_task_struct(task_struct);
54	/*
55	 * As for a vfork(2), task_struct->vfork_done (pointing to the
56	 * underlying kthread->exited) can be used to wait for the end of a
57	 * kernel thread. It is set to NULL when the thread exits, so we
58	 * keep a copy here.
59	 */
60	task_done = task_struct->vfork_done;
61	wake_up_process(task_struct);
62
63	time_remaining = wait_for_completion_timeout(
64		task_done, try_catch->timeout);
65	if (time_remaining == 0) {
66		try_catch->try_result = -ETIMEDOUT;
67		kthread_stop(task_struct);
68	}
69
70	put_task_struct(task_struct);
71	exit_code = try_catch->try_result;
72
73	if (!exit_code)
74		return;
75
76	if (exit_code == -EFAULT)
77		try_catch->try_result = 0;
78	else if (exit_code == -EINTR) {
79		if (test->last_seen.file)
80			kunit_err(test, "try faulted: last line seen %s:%d\n",
81				  test->last_seen.file, test->last_seen.line);
82		else
83			kunit_err(test, "try faulted\n");
84	} else if (exit_code == -ETIMEDOUT)
85		kunit_err(test, "try timed out\n");
86	else if (exit_code)
87		kunit_err(test, "Unknown error: %d\n", exit_code);
88
89	try_catch->catch(try_catch->context);
90}
91EXPORT_SYMBOL_GPL(kunit_try_catch_run);
~/ Read-only file preview.