Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _LINUX_UNWIND_USER_DEFERRED_H
3#define _LINUX_UNWIND_USER_DEFERRED_H
4
5#include <linux/task_work.h>
6#include <linux/unwind_user.h>
7#include <linux/unwind_deferred_types.h>
8
9struct unwind_work;
10
11typedef void (*unwind_callback_t)(struct unwind_work *work, struct unwind_stacktrace *trace, u64 cookie);
12
13struct unwind_work {
14 struct list_head list;
15 unwind_callback_t func;
16 int bit;
17};
18
19#ifdef CONFIG_UNWIND_USER
20
21enum {
22 UNWIND_PENDING_BIT = 0,
23 UNWIND_USED_BIT,
24};
25
26enum {
27 UNWIND_PENDING = BIT(UNWIND_PENDING_BIT),
28
29 /* Set if the unwinding was used (directly or deferred) */
30 UNWIND_USED = BIT(UNWIND_USED_BIT)
31};
32
33void unwind_task_init(struct task_struct *task);
34void unwind_task_free(struct task_struct *task);
35
36int unwind_user_faultable(struct unwind_stacktrace *trace);
37
38int unwind_deferred_init(struct unwind_work *work, unwind_callback_t func);
39int unwind_deferred_request(struct unwind_work *work, u64 *cookie);
40void unwind_deferred_cancel(struct unwind_work *work);
41
42void unwind_deferred_task_exit(struct task_struct *task);
43
44static __always_inline void unwind_reset_info(void)
45{
46 struct unwind_task_info *info = ¤t->unwind_info;
47 unsigned long bits;
48
49 /* Was there any unwinding? */
50 if (unlikely(info->unwind_mask)) {
51 bits = info->unwind_mask;
52 do {
53 /* Is a task_work going to run again before going back */
54 if (bits & UNWIND_PENDING)
55 return;
56 } while (!try_cmpxchg(&info->unwind_mask, &bits, 0UL));
57 current->unwind_info.id.id = 0;
58
59 if (unlikely(info->cache)) {
60 info->cache->nr_entries = 0;
61 info->cache->unwind_completed = 0;
62 }
63 }
64}
65
66#else /* !CONFIG_UNWIND_USER */
67
68static inline void unwind_task_init(struct task_struct *task) {}
69static inline void unwind_task_free(struct task_struct *task) {}
70
71static inline int unwind_user_faultable(struct unwind_stacktrace *trace) { return -ENOSYS; }
72static inline int unwind_deferred_init(struct unwind_work *work, unwind_callback_t func) { return -ENOSYS; }
73static inline int unwind_deferred_request(struct unwind_work *work, u64 *timestamp) { return -ENOSYS; }
74static inline void unwind_deferred_cancel(struct unwind_work *work) {}
75
76static inline void unwind_deferred_task_exit(struct task_struct *task) {}
77static inline void unwind_reset_info(void) {}
78
79#endif /* !CONFIG_UNWIND_USER */
80
81#endif /* _LINUX_UNWIND_USER_DEFERRED_H */