.. | .. |
---|
4 | 4 | |
---|
5 | 5 | #include <linux/spinlock.h> |
---|
6 | 6 | #include <linux/list.h> |
---|
7 | | -#include <linux/sched.h> |
---|
8 | | -#include <linux/timex.h> |
---|
| 7 | +#include <linux/mutex.h> |
---|
9 | 8 | #include <linux/alarmtimer.h> |
---|
| 9 | +#include <linux/timerqueue.h> |
---|
| 10 | +#include <linux/task_work.h> |
---|
10 | 11 | |
---|
11 | | -struct siginfo; |
---|
12 | | - |
---|
13 | | -struct cpu_timer_list { |
---|
14 | | - struct list_head entry; |
---|
15 | | - u64 expires, incr; |
---|
16 | | - struct task_struct *task; |
---|
17 | | - int firing; |
---|
18 | | -}; |
---|
| 12 | +struct kernel_siginfo; |
---|
| 13 | +struct task_struct; |
---|
19 | 14 | |
---|
20 | 15 | /* |
---|
21 | 16 | * Bit fields within a clockid: |
---|
.. | .. |
---|
63 | 58 | return ~(clk >> 3); |
---|
64 | 59 | } |
---|
65 | 60 | |
---|
| 61 | +#ifdef CONFIG_POSIX_TIMERS |
---|
| 62 | + |
---|
| 63 | +/** |
---|
| 64 | + * cpu_timer - Posix CPU timer representation for k_itimer |
---|
| 65 | + * @node: timerqueue node to queue in the task/sig |
---|
| 66 | + * @head: timerqueue head on which this timer is queued |
---|
| 67 | + * @pid: Pointer to target task PID |
---|
| 68 | + * @elist: List head for the expiry list |
---|
| 69 | + * @firing: Timer is currently firing |
---|
| 70 | + * @handling: Pointer to the task which handles expiry |
---|
| 71 | + */ |
---|
| 72 | +struct cpu_timer { |
---|
| 73 | + struct timerqueue_node node; |
---|
| 74 | + struct timerqueue_head *head; |
---|
| 75 | + struct pid *pid; |
---|
| 76 | + struct list_head elist; |
---|
| 77 | + int firing; |
---|
| 78 | + struct task_struct __rcu *handling; |
---|
| 79 | +}; |
---|
| 80 | + |
---|
| 81 | +static inline bool cpu_timer_enqueue(struct timerqueue_head *head, |
---|
| 82 | + struct cpu_timer *ctmr) |
---|
| 83 | +{ |
---|
| 84 | + ctmr->head = head; |
---|
| 85 | + return timerqueue_add(head, &ctmr->node); |
---|
| 86 | +} |
---|
| 87 | + |
---|
| 88 | +static inline void cpu_timer_dequeue(struct cpu_timer *ctmr) |
---|
| 89 | +{ |
---|
| 90 | + if (ctmr->head) { |
---|
| 91 | + timerqueue_del(ctmr->head, &ctmr->node); |
---|
| 92 | + ctmr->head = NULL; |
---|
| 93 | + } |
---|
| 94 | +} |
---|
| 95 | + |
---|
| 96 | +static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr) |
---|
| 97 | +{ |
---|
| 98 | + return ctmr->node.expires; |
---|
| 99 | +} |
---|
| 100 | + |
---|
| 101 | +static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp) |
---|
| 102 | +{ |
---|
| 103 | + ctmr->node.expires = exp; |
---|
| 104 | +} |
---|
| 105 | + |
---|
| 106 | +/** |
---|
| 107 | + * posix_cputimer_base - Container per posix CPU clock |
---|
| 108 | + * @nextevt: Earliest-expiration cache |
---|
| 109 | + * @tqhead: timerqueue head for cpu_timers |
---|
| 110 | + */ |
---|
| 111 | +struct posix_cputimer_base { |
---|
| 112 | + u64 nextevt; |
---|
| 113 | + struct timerqueue_head tqhead; |
---|
| 114 | +}; |
---|
| 115 | + |
---|
| 116 | +/** |
---|
| 117 | + * posix_cputimers - Container for posix CPU timer related data |
---|
| 118 | + * @bases: Base container for posix CPU clocks |
---|
| 119 | + * @timers_active: Timers are queued. |
---|
| 120 | + * @expiry_active: Timer expiry is active. Used for |
---|
| 121 | + * process wide timers to avoid multiple |
---|
| 122 | + * task trying to handle expiry concurrently |
---|
| 123 | + * |
---|
| 124 | + * Used in task_struct and signal_struct |
---|
| 125 | + */ |
---|
| 126 | +struct posix_cputimers { |
---|
| 127 | + struct posix_cputimer_base bases[CPUCLOCK_MAX]; |
---|
| 128 | + unsigned int timers_active; |
---|
| 129 | + unsigned int expiry_active; |
---|
| 130 | +}; |
---|
| 131 | + |
---|
| 132 | +/** |
---|
| 133 | + * posix_cputimers_work - Container for task work based posix CPU timer expiry |
---|
| 134 | + * @work: The task work to be scheduled |
---|
| 135 | + * @mutex: Mutex held around expiry in context of this task work |
---|
| 136 | + * @scheduled: @work has been scheduled already, no further processing |
---|
| 137 | + */ |
---|
| 138 | +struct posix_cputimers_work { |
---|
| 139 | + struct callback_head work; |
---|
| 140 | + struct mutex mutex; |
---|
| 141 | + unsigned int scheduled; |
---|
| 142 | +}; |
---|
| 143 | + |
---|
| 144 | +static inline void posix_cputimers_init(struct posix_cputimers *pct) |
---|
| 145 | +{ |
---|
| 146 | + memset(pct, 0, sizeof(*pct)); |
---|
| 147 | + pct->bases[0].nextevt = U64_MAX; |
---|
| 148 | + pct->bases[1].nextevt = U64_MAX; |
---|
| 149 | + pct->bases[2].nextevt = U64_MAX; |
---|
| 150 | +} |
---|
| 151 | + |
---|
| 152 | +void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit); |
---|
| 153 | + |
---|
| 154 | +static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct, |
---|
| 155 | + u64 runtime) |
---|
| 156 | +{ |
---|
| 157 | + pct->bases[CPUCLOCK_SCHED].nextevt = runtime; |
---|
| 158 | +} |
---|
| 159 | + |
---|
| 160 | +/* Init task static initializer */ |
---|
| 161 | +#define INIT_CPU_TIMERBASE(b) { \ |
---|
| 162 | + .nextevt = U64_MAX, \ |
---|
| 163 | +} |
---|
| 164 | + |
---|
| 165 | +#define INIT_CPU_TIMERBASES(b) { \ |
---|
| 166 | + INIT_CPU_TIMERBASE(b[0]), \ |
---|
| 167 | + INIT_CPU_TIMERBASE(b[1]), \ |
---|
| 168 | + INIT_CPU_TIMERBASE(b[2]), \ |
---|
| 169 | +} |
---|
| 170 | + |
---|
| 171 | +#define INIT_CPU_TIMERS(s) \ |
---|
| 172 | + .posix_cputimers = { \ |
---|
| 173 | + .bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \ |
---|
| 174 | + }, |
---|
| 175 | +#else |
---|
| 176 | +struct posix_cputimers { }; |
---|
| 177 | +struct cpu_timer { }; |
---|
| 178 | +#define INIT_CPU_TIMERS(s) |
---|
| 179 | +static inline void posix_cputimers_init(struct posix_cputimers *pct) { } |
---|
| 180 | +static inline void posix_cputimers_group_init(struct posix_cputimers *pct, |
---|
| 181 | + u64 cpu_limit) { } |
---|
| 182 | +#endif |
---|
| 183 | + |
---|
| 184 | +#ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK |
---|
| 185 | +void clear_posix_cputimers_work(struct task_struct *p); |
---|
| 186 | +void posix_cputimers_init_work(void); |
---|
| 187 | +#else |
---|
| 188 | +static inline void clear_posix_cputimers_work(struct task_struct *p) { } |
---|
| 189 | +static inline void posix_cputimers_init_work(void) { } |
---|
| 190 | +#endif |
---|
| 191 | + |
---|
66 | 192 | #define REQUEUE_PENDING 1 |
---|
67 | 193 | |
---|
68 | 194 | /** |
---|
.. | .. |
---|
85 | 211 | * @it_process: The task to wakeup on clock_nanosleep (CPU timers) |
---|
86 | 212 | * @sigq: Pointer to preallocated sigqueue |
---|
87 | 213 | * @it: Union representing the various posix timer type |
---|
88 | | - * internals. Also used for rcu freeing the timer. |
---|
| 214 | + * internals. |
---|
| 215 | + * @rcu: RCU head for freeing the timer. |
---|
89 | 216 | */ |
---|
90 | 217 | struct k_itimer { |
---|
91 | 218 | struct list_head list; |
---|
.. | .. |
---|
110 | 237 | struct { |
---|
111 | 238 | struct hrtimer timer; |
---|
112 | 239 | } real; |
---|
113 | | - struct cpu_timer_list cpu; |
---|
| 240 | + struct cpu_timer cpu; |
---|
114 | 241 | struct { |
---|
115 | 242 | struct alarm alarmtimer; |
---|
116 | 243 | } alarm; |
---|
117 | | - struct rcu_head rcu; |
---|
118 | 244 | } it; |
---|
| 245 | + struct rcu_head rcu; |
---|
119 | 246 | }; |
---|
120 | 247 | |
---|
121 | | -void run_posix_cpu_timers(struct task_struct *task); |
---|
| 248 | +void run_posix_cpu_timers(void); |
---|
122 | 249 | void posix_cpu_timers_exit(struct task_struct *task); |
---|
123 | 250 | void posix_cpu_timers_exit_group(struct task_struct *task); |
---|
124 | 251 | void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, |
---|
.. | .. |
---|
126 | 253 | |
---|
127 | 254 | void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); |
---|
128 | 255 | |
---|
129 | | -void posixtimer_rearm(struct siginfo *info); |
---|
| 256 | +void posixtimer_rearm(struct kernel_siginfo *info); |
---|
130 | 257 | #endif |
---|