linux/include/linux/sched/task_stack.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _LINUX_SCHED_TASK_STACK_H
   3#define _LINUX_SCHED_TASK_STACK_H
   4
   5/*
   6 * task->stack (kernel stack) handling interfaces:
   7 */
   8
   9#include <linux/sched.h>
  10#include <linux/magic.h>
  11
  12#ifdef CONFIG_THREAD_INFO_IN_TASK
  13
  14/*
  15 * When accessing the stack of a non-current task that might exit, use
  16 * try_get_task_stack() instead.  task_stack_page will return a pointer
  17 * that could get freed out from under you.
  18 */
  19static __always_inline void *task_stack_page(const struct task_struct *task)
  20{
  21        return task->stack;
  22}
  23
  24#define setup_thread_stack(new,old)     do { } while(0)
  25
  26static inline unsigned long *end_of_stack(const struct task_struct *task)
  27{
  28#ifdef CONFIG_STACK_GROWSUP
  29        return (unsigned long *)((unsigned long)task->stack + THREAD_SIZE) - 1;
  30#else
  31        return task->stack;
  32#endif
  33}
  34
  35#elif !defined(__HAVE_THREAD_FUNCTIONS)
  36
  37#define task_stack_page(task)   ((void *)(task)->stack)
  38
  39static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
  40{
  41        *task_thread_info(p) = *task_thread_info(org);
  42        task_thread_info(p)->task = p;
  43}
  44
  45/*
  46 * Return the address of the last usable long on the stack.
  47 *
  48 * When the stack grows down, this is just above the thread
  49 * info struct. Going any lower will corrupt the threadinfo.
  50 *
  51 * When the stack grows up, this is the highest address.
  52 * Beyond that position, we corrupt data on the next page.
  53 */
  54static inline unsigned long *end_of_stack(struct task_struct *p)
  55{
  56#ifdef CONFIG_STACK_GROWSUP
  57        return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1;
  58#else
  59        return (unsigned long *)(task_thread_info(p) + 1);
  60#endif
  61}
  62
  63#endif
  64
  65#ifdef CONFIG_THREAD_INFO_IN_TASK
  66static inline void *try_get_task_stack(struct task_struct *tsk)
  67{
  68        return refcount_inc_not_zero(&tsk->stack_refcount) ?
  69                task_stack_page(tsk) : NULL;
  70}
  71
  72extern void put_task_stack(struct task_struct *tsk);
  73#else
  74static inline void *try_get_task_stack(struct task_struct *tsk)
  75{
  76        return task_stack_page(tsk);
  77}
  78
  79static inline void put_task_stack(struct task_struct *tsk) {}
  80#endif
  81
  82void exit_task_stack_account(struct task_struct *tsk);
  83
  84#define task_stack_end_corrupted(task) \
  85                (*(end_of_stack(task)) != STACK_END_MAGIC)
  86
  87static inline int object_is_on_stack(const void *obj)
  88{
  89        void *stack = task_stack_page(current);
  90
  91        return (obj >= stack) && (obj < (stack + THREAD_SIZE));
  92}
  93
  94extern void thread_stack_cache_init(void);
  95
  96#ifdef CONFIG_DEBUG_STACK_USAGE
  97static inline unsigned long stack_not_used(struct task_struct *p)
  98{
  99        unsigned long *n = end_of_stack(p);
 100
 101        do {    /* Skip over canary */
 102# ifdef CONFIG_STACK_GROWSUP
 103                n--;
 104# else
 105                n++;
 106# endif
 107        } while (!*n);
 108
 109# ifdef CONFIG_STACK_GROWSUP
 110        return (unsigned long)end_of_stack(p) - (unsigned long)n;
 111# else
 112        return (unsigned long)n - (unsigned long)end_of_stack(p);
 113# endif
 114}
 115#endif
 116extern void set_task_stack_end_magic(struct task_struct *tsk);
 117
 118#ifndef __HAVE_ARCH_KSTACK_END
 119static inline int kstack_end(void *addr)
 120{
 121        /* Reliable end of stack detection:
 122         * Some APM bios versions misalign the stack
 123         */
 124        return !(((unsigned long)addr+sizeof(void*)-1) & (THREAD_SIZE-sizeof(void*)));
 125}
 126#endif
 127
 128#endif /* _LINUX_SCHED_TASK_STACK_H */
 129