at master 2.2 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 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 = &current->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 */