| .. | .. |
|---|
| 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 | | - int firing_cpu; |
|---|
| 19 | | -}; |
|---|
| 12 | +struct kernel_siginfo; |
|---|
| 13 | +struct task_struct; |
|---|
| 20 | 14 | |
|---|
| 21 | 15 | /* |
|---|
| 22 | 16 | * Bit fields within a clockid: |
|---|
| .. | .. |
|---|
| 64 | 58 | return ~(clk >> 3); |
|---|
| 65 | 59 | } |
|---|
| 66 | 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 | + |
|---|
| 67 | 192 | #define REQUEUE_PENDING 1 |
|---|
| 68 | 193 | |
|---|
| 69 | 194 | /** |
|---|
| .. | .. |
|---|
| 86 | 211 | * @it_process: The task to wakeup on clock_nanosleep (CPU timers) |
|---|
| 87 | 212 | * @sigq: Pointer to preallocated sigqueue |
|---|
| 88 | 213 | * @it: Union representing the various posix timer type |
|---|
| 89 | | - * internals. Also used for rcu freeing the timer. |
|---|
| 214 | + * internals. |
|---|
| 215 | + * @rcu: RCU head for freeing the timer. |
|---|
| 90 | 216 | */ |
|---|
| 91 | 217 | struct k_itimer { |
|---|
| 92 | 218 | struct list_head list; |
|---|
| .. | .. |
|---|
| 111 | 237 | struct { |
|---|
| 112 | 238 | struct hrtimer timer; |
|---|
| 113 | 239 | } real; |
|---|
| 114 | | - struct cpu_timer_list cpu; |
|---|
| 240 | + struct cpu_timer cpu; |
|---|
| 115 | 241 | struct { |
|---|
| 116 | 242 | struct alarm alarmtimer; |
|---|
| 117 | 243 | } alarm; |
|---|
| .. | .. |
|---|
| 119 | 245 | struct rcu_head rcu; |
|---|
| 120 | 246 | }; |
|---|
| 121 | 247 | |
|---|
| 122 | | -void run_posix_cpu_timers(struct task_struct *task); |
|---|
| 248 | +void run_posix_cpu_timers(void); |
|---|
| 123 | 249 | void posix_cpu_timers_exit(struct task_struct *task); |
|---|
| 124 | 250 | void posix_cpu_timers_exit_group(struct task_struct *task); |
|---|
| 125 | 251 | void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, |
|---|
| .. | .. |
|---|
| 127 | 253 | |
|---|
| 128 | 254 | void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); |
|---|
| 129 | 255 | |
|---|
| 130 | | -void posixtimer_rearm(struct siginfo *info); |
|---|
| 256 | +void posixtimer_rearm(struct kernel_siginfo *info); |
|---|
| 131 | 257 | #endif |
|---|