at v6.18 81 lines 2.4 kB view raw
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 = &current->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 */