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
9#ifdef CONFIG_UNWIND_USER
10
11enum {
12 UNWIND_PENDING_BIT = 0,
13 UNWIND_USED_BIT,
14};
15
16enum {
17 UNWIND_PENDING = BIT(UNWIND_PENDING_BIT),
18
19 /* Set if the unwinding was used (directly or deferred) */
20 UNWIND_USED = BIT(UNWIND_USED_BIT)
21};
22
23void unwind_task_init(struct task_struct *task);
24void unwind_task_free(struct task_struct *task);
25
26int unwind_user_faultable(struct unwind_stacktrace *trace);
27
28int unwind_deferred_init(struct unwind_work *work, unwind_callback_t func);
29int unwind_deferred_request(struct unwind_work *work, u64 *cookie);
30void unwind_deferred_cancel(struct unwind_work *work);
31
32void unwind_deferred_task_exit(struct task_struct *task);
33
34static __always_inline void unwind_reset_info(void)
35{
36 struct unwind_task_info *info = ¤t->unwind_info;
37 unsigned long bits = atomic_long_read(&info->unwind_mask);
38
39 /* Was there any unwinding? */
40 if (likely(!bits))
41 return;
42
43 do {
44 /* Is a task_work going to run again before going back */
45 if (bits & UNWIND_PENDING)
46 return;
47 } while (!atomic_long_try_cmpxchg(&info->unwind_mask, &bits, 0UL));
48 current->unwind_info.id.id = 0;
49
50 if (unlikely(info->cache)) {
51 info->cache->nr_entries = 0;
52 info->cache->unwind_completed = 0;
53 }
54}
55
56#else /* !CONFIG_UNWIND_USER */
57
58static inline void unwind_task_init(struct task_struct *task) {}
59static inline void unwind_task_free(struct task_struct *task) {}
60
61static inline int unwind_user_faultable(struct unwind_stacktrace *trace)
62{ return -ENOSYS; }
63
64static inline int
65unwind_deferred_init(struct unwind_work *work, unwind_callback_t func)
66{ return -ENOSYS; }
67
68static inline int
69unwind_deferred_request(struct unwind_work *work, u64 *timestamp)
70{ return -ENOSYS; }
71
72static inline void unwind_deferred_cancel(struct unwind_work *work) {}
73
74static inline void unwind_deferred_task_exit(struct task_struct *task) {}
75static inline void unwind_reset_info(void) {}
76
77#endif /* !CONFIG_UNWIND_USER */
78
79#endif /* _LINUX_UNWIND_USER_DEFERRED_H */