Blame view

kernel/time/posix-timers.c 37.1 KB
35728b820   Thomas Gleixner   time: Add SPDX li...
1
  // SPDX-License-Identifier: GPL-2.0+
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
   * 2002-10-15  Posix Clocks & timers
   *                           by George Anzinger george@mvista.com
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
   *			     Copyright (C) 2002 2003 by MontaVista Software.
   *
   * 2004-06-01  Fix CLOCK_REALTIME clock/timer TIMER_ABSTIME bug.
   *			     Copyright (C) 2004 Boris Hu
   *
0141de741   Thomas Gleixner   posix-timers: Rem...
10
   * These are all the functions necessary to implement POSIX clocks & timers
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
   */
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
  #include <linux/interrupt.h>
  #include <linux/slab.h>
  #include <linux/time.h>
97d1f15b7   Arjan van de Ven   [PATCH] sem2mutex...
16
  #include <linux/mutex.h>
61855b6b0   Ingo Molnar   sched/headers: Pr...
17
  #include <linux/sched/task.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
19
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
  #include <linux/list.h>
  #include <linux/init.h>
  #include <linux/compiler.h>
5ed67f05f   Pavel Emelyanov   posix timers: All...
23
  #include <linux/hash.h>
0606f422b   Richard Cochran   posix clocks: Int...
24
  #include <linux/posix-clock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
  #include <linux/posix-timers.h>
  #include <linux/syscalls.h>
  #include <linux/wait.h>
  #include <linux/workqueue.h>
9984de1a5   Paul Gortmaker   kernel: Map most ...
29
  #include <linux/export.h>
5ed67f05f   Pavel Emelyanov   posix timers: All...
30
  #include <linux/hashtable.h>
edbeda463   Al Viro   time/posix-timers...
31
  #include <linux/compat.h>
19b558db1   Thomas Gleixner   posix-timers: Pro...
32
  #include <linux/nospec.h>
5a590f35a   Andrei Vagin   posix-clocks: Wir...
33
  #include <linux/time_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

8b094cd03   Thomas Gleixner   time: Consolidate...
35
  #include "timekeeping.h"
bab0aae9d   Thomas Gleixner   posix-timers: Mov...
36
  #include "posix-timers.h"
8b094cd03   Thomas Gleixner   time: Consolidate...
37

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  /*
5ed67f05f   Pavel Emelyanov   posix timers: All...
39
40
41
42
43
44
   * Management arrays for POSIX timers. Timers are now kept in static hash table
   * with 512 entries.
   * Timer ids are allocated by local routine, which selects proper hash head by
   * key, constructed from current->signal address and per signal struct counter.
   * This keeps timer ids unique per process, but now they can intersect between
   * processes.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
   */
  
  /*
   * Lets keep our timers in a slab cache :-)
   */
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
50
  static struct kmem_cache *posix_timers_cache;
5ed67f05f   Pavel Emelyanov   posix timers: All...
51
52
53
  
  static DEFINE_HASHTABLE(posix_timers_hashtable, 9);
  static DEFINE_SPINLOCK(hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54

6631fa12c   Thomas Gleixner   posix-timers: Avo...
55
56
  static const struct k_clock * const posix_clocks[];
  static const struct k_clock *clockid_to_kclock(const clockid_t id);
67edab48c   Thomas Gleixner   posix-timers: Han...
57
  static const struct k_clock clock_realtime, clock_monotonic;
6631fa12c   Thomas Gleixner   posix-timers: Avo...
58

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
65
66
   * we assume that the new SIGEV_THREAD_ID shares no bits with the other
   * SIGEV values.  Here we put out an error if this assumption fails.
   */
  #if SIGEV_THREAD_ID != (SIGEV_THREAD_ID & \
                         ~(SIGEV_SIGNAL | SIGEV_NONE | SIGEV_THREAD))
  #error "SIGEV_THREAD_ID must not share bit with other SIGEV values!"
  #endif
65da528d7   Thomas Gleixner   posix-timers: Def...
67
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
71
72
73
74
75
76
77
78
   * The timer ID is turned into a timer address by idr_find().
   * Verifying a valid ID consists of:
   *
   * a) checking that idr_find() returns other than -1.
   * b) checking that the timer id matches the one in the timer itself.
   * c) that the timer owner is in the callers thread group.
   */
  
  /*
   * CLOCKs: The POSIX standard calls for a couple of clocks and allows us
   *	    to implement others.  This structure defines the various
0061748dd   Richard Cochran   posix-timer: Upda...
79
   *	    clocks.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
83
84
85
86
87
88
   *
   * RESOLUTION: Clock resolution is used to round up timer and interval
   *	    times, NOT to report clock times, which are reported with as
   *	    much resolution as the system can muster.  In some cases this
   *	    resolution may depend on the underlying clock hardware and
   *	    may not be quantifiable until run time, and only then is the
   *	    necessary code is written.	The standard says we should say
   *	    something about this issue in the documentation...
   *
0061748dd   Richard Cochran   posix-timer: Upda...
89
90
   * FUNCTIONS: The CLOCKs structure defines possible functions to
   *	    handle various clock functions.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
   *
0061748dd   Richard Cochran   posix-timer: Upda...
92
93
94
95
   *	    The standard POSIX timer management code assumes the
   *	    following: 1.) The k_itimer struct (sched.h) is used for
   *	    the timer.  2.) The list, it_lock, it_clock, it_id and
   *	    it_pid fields are not modified by timer code.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
99
100
101
102
103
   *
   * Permissions: It is assumed that the clock_settime() function defined
   *	    for each clock will take care of permission checks.	 Some
   *	    clocks may be set able by any user (i.e. local process
   *	    clocks) others not.	 Currently the only set able clock we
   *	    have is CLOCK_REALTIME and its high res counter part, both of
   *	    which we beg off on and pass to do_sys_settimeofday().
   */
20f33a03f   Namhyung Kim   posix-timers: Ann...
104
105
106
107
108
109
110
  static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags);
  
  #define lock_timer(tid, flags)						   \
  ({	struct k_itimer *__timr;					   \
  	__cond_lock(&__timr->it_lock, __timr = __lock_timer(tid, flags));  \
  	__timr;								   \
  })
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111

5ed67f05f   Pavel Emelyanov   posix timers: All...
112
113
114
115
116
117
118
119
120
  static int hash(struct signal_struct *sig, unsigned int nr)
  {
  	return hash_32(hash32_ptr(sig) ^ nr, HASH_BITS(posix_timers_hashtable));
  }
  
  static struct k_itimer *__posix_timers_find(struct hlist_head *head,
  					    struct signal_struct *sig,
  					    timer_t id)
  {
5ed67f05f   Pavel Emelyanov   posix timers: All...
121
  	struct k_itimer *timer;
5fb1c2a5b   Amol Grover   posix-timers: Pas...
122
123
  	hlist_for_each_entry_rcu(timer, head, t_hash,
  				 lockdep_is_held(&hash_lock)) {
5ed67f05f   Pavel Emelyanov   posix timers: All...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  		if ((timer->it_signal == sig) && (timer->it_id == id))
  			return timer;
  	}
  	return NULL;
  }
  
  static struct k_itimer *posix_timer_by_id(timer_t id)
  {
  	struct signal_struct *sig = current->signal;
  	struct hlist_head *head = &posix_timers_hashtable[hash(sig, id)];
  
  	return __posix_timers_find(head, sig, id);
  }
  
  static int posix_timer_add(struct k_itimer *timer)
  {
  	struct signal_struct *sig = current->signal;
  	int first_free_id = sig->posix_timer_id;
  	struct hlist_head *head;
  	int ret = -ENOENT;
  
  	do {
  		spin_lock(&hash_lock);
  		head = &posix_timers_hashtable[hash(sig, sig->posix_timer_id)];
  		if (!__posix_timers_find(head, sig, sig->posix_timer_id)) {
  			hlist_add_head_rcu(&timer->t_hash, head);
  			ret = sig->posix_timer_id;
  		}
  		if (++sig->posix_timer_id < 0)
  			sig->posix_timer_id = 0;
  		if ((sig->posix_timer_id == first_free_id) && (ret == -ENOENT))
  			/* Loop over all possible ids completed */
  			ret = -EAGAIN;
  		spin_unlock(&hash_lock);
  	} while (ret == -ENOENT);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
164
  static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
  {
  	spin_unlock_irqrestore(&timr->it_lock, flags);
  }
422857776   Thomas Gleixner   posix-timers: Con...
165
  /* Get clock_realtime */
eaf80194d   Andrei Vagin   posix-clocks: Ren...
166
  static int posix_get_realtime_timespec(clockid_t which_clock, struct timespec64 *tp)
422857776   Thomas Gleixner   posix-timers: Con...
167
  {
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
168
  	ktime_get_real_ts64(tp);
422857776   Thomas Gleixner   posix-timers: Con...
169
170
  	return 0;
  }
9c71a2e8a   Andrei Vagin   posix-clocks: Int...
171
172
173
174
  static ktime_t posix_get_realtime_ktime(clockid_t which_clock)
  {
  	return ktime_get_real();
  }
26f9a4796   Thomas Gleixner   posix-timers: Con...
175
176
  /* Set clock_realtime */
  static int posix_clock_realtime_set(const clockid_t which_clock,
0fe6afe38   Deepa Dinamani   time: Change k_cl...
177
  				    const struct timespec64 *tp)
26f9a4796   Thomas Gleixner   posix-timers: Con...
178
  {
0fe6afe38   Deepa Dinamani   time: Change k_cl...
179
  	return do_sys_settimeofday64(tp, NULL);
26f9a4796   Thomas Gleixner   posix-timers: Con...
180
  }
f1f1d5ebd   Richard Cochran   posix-timers: Int...
181
  static int posix_clock_realtime_adj(const clockid_t which_clock,
ead25417f   Deepa Dinamani   timex: use __kern...
182
  				    struct __kernel_timex *t)
f1f1d5ebd   Richard Cochran   posix-timers: Int...
183
184
185
  {
  	return do_adjtimex(t);
  }
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
186
187
188
  /*
   * Get monotonic time for posix timers
   */
eaf80194d   Andrei Vagin   posix-clocks: Ren...
189
  static int posix_get_monotonic_timespec(clockid_t which_clock, struct timespec64 *tp)
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
190
  {
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
191
  	ktime_get_ts64(tp);
5a590f35a   Andrei Vagin   posix-clocks: Wir...
192
  	timens_add_monotonic(tp);
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
193
194
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195

9c71a2e8a   Andrei Vagin   posix-clocks: Int...
196
197
198
199
  static ktime_t posix_get_monotonic_ktime(clockid_t which_clock)
  {
  	return ktime_get();
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  /*
7fdd7f890   John Stultz   timers: Export CL...
201
   * Get monotonic-raw time for posix timers
2d42244ae   John Stultz   clocksource: intr...
202
   */
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
203
  static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec64 *tp)
2d42244ae   John Stultz   clocksource: intr...
204
  {
58a10456d   Arnd Bergmann   posix-timers: Use...
205
  	ktime_get_raw_ts64(tp);
5a590f35a   Andrei Vagin   posix-clocks: Wir...
206
  	timens_add_monotonic(tp);
2d42244ae   John Stultz   clocksource: intr...
207
208
  	return 0;
  }
da15cfdae   John Stultz   time: Introduce C...
209

3c9c12f4b   Deepa Dinamani   time: Change k_cl...
210
  static int posix_get_realtime_coarse(clockid_t which_clock, struct timespec64 *tp)
da15cfdae   John Stultz   time: Introduce C...
211
  {
58a10456d   Arnd Bergmann   posix-timers: Use...
212
  	ktime_get_coarse_real_ts64(tp);
da15cfdae   John Stultz   time: Introduce C...
213
214
215
216
  	return 0;
  }
  
  static int posix_get_monotonic_coarse(clockid_t which_clock,
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
217
  						struct timespec64 *tp)
da15cfdae   John Stultz   time: Introduce C...
218
  {
58a10456d   Arnd Bergmann   posix-timers: Use...
219
  	ktime_get_coarse_ts64(tp);
5a590f35a   Andrei Vagin   posix-clocks: Wir...
220
  	timens_add_monotonic(tp);
da15cfdae   John Stultz   time: Introduce C...
221
222
  	return 0;
  }
d2e3e0ca5   Deepa Dinamani   time: Change k_cl...
223
  static int posix_get_coarse_res(const clockid_t which_clock, struct timespec64 *tp)
da15cfdae   John Stultz   time: Introduce C...
224
  {
d2e3e0ca5   Deepa Dinamani   time: Change k_cl...
225
  	*tp = ktime_to_timespec64(KTIME_LOW_RES);
da15cfdae   John Stultz   time: Introduce C...
226
227
  	return 0;
  }
7fdd7f890   John Stultz   timers: Export CL...
228

eaf80194d   Andrei Vagin   posix-clocks: Ren...
229
  static int posix_get_boottime_timespec(const clockid_t which_clock, struct timespec64 *tp)
7fdd7f890   John Stultz   timers: Export CL...
230
  {
58a10456d   Arnd Bergmann   posix-timers: Use...
231
  	ktime_get_boottime_ts64(tp);
5a590f35a   Andrei Vagin   posix-clocks: Wir...
232
  	timens_add_boottime(tp);
7fdd7f890   John Stultz   timers: Export CL...
233
234
  	return 0;
  }
9c71a2e8a   Andrei Vagin   posix-clocks: Int...
235
236
237
238
  static ktime_t posix_get_boottime_ktime(const clockid_t which_clock)
  {
  	return ktime_get_boottime();
  }
eaf80194d   Andrei Vagin   posix-clocks: Ren...
239
  static int posix_get_tai_timespec(clockid_t which_clock, struct timespec64 *tp)
1ff3c9677   John Stultz   timekeeping: Add ...
240
  {
58a10456d   Arnd Bergmann   posix-timers: Use...
241
  	ktime_get_clocktai_ts64(tp);
1ff3c9677   John Stultz   timekeeping: Add ...
242
243
  	return 0;
  }
7fdd7f890   John Stultz   timers: Export CL...
244

9c71a2e8a   Andrei Vagin   posix-clocks: Int...
245
246
247
248
  static ktime_t posix_get_tai_ktime(clockid_t which_clock)
  {
  	return ktime_get_clocktai();
  }
d2e3e0ca5   Deepa Dinamani   time: Change k_cl...
249
  static int posix_get_hrtimer_res(clockid_t which_clock, struct timespec64 *tp)
056a3cacb   Thomas Gleixner   hrtimer: Get rid ...
250
251
252
253
254
  {
  	tp->tv_sec = 0;
  	tp->tv_nsec = hrtimer_resolution;
  	return 0;
  }
2d42244ae   John Stultz   clocksource: intr...
255
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
258
259
   * Initialize everything, well, just everything in Posix clocks/timers ;)
   */
  static __init int init_posix_timers(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  	posix_timers_cache = kmem_cache_create("posix_timers_cache",
040b5c6f9   Alexey Dobriyan   SLAB_PANIC more (...
261
262
  					sizeof (struct k_itimer), 0, SLAB_PANIC,
  					NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  __initcall(init_posix_timers);
78c9c4dfb   Thomas Gleixner   posix-timers: San...
266
267
268
269
270
271
272
273
274
275
  /*
   * The siginfo si_overrun field and the return value of timer_getoverrun(2)
   * are of type int. Clamp the overrun value to INT_MAX
   */
  static inline int timer_overrun_to_int(struct k_itimer *timr, int baseval)
  {
  	s64 sum = timr->it_overrun_last + (s64)baseval;
  
  	return sum > (s64)INT_MAX ? INT_MAX : (int)sum;
  }
f37fb0aa4   Thomas Gleixner   posix-timers: Use...
276
  static void common_hrtimer_rearm(struct k_itimer *timr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  {
44f214755   Roman Zippel   [PATCH] hrtimers:...
278
  	struct hrtimer *timer = &timr->it.real.timer;
78c9c4dfb   Thomas Gleixner   posix-timers: San...
279
280
  	timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(),
  					    timr->it_interval);
44f214755   Roman Zippel   [PATCH] hrtimers:...
281
  	hrtimer_restart(timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
286
287
288
289
290
291
  }
  
  /*
   * This function is exported for use by the signal deliver code.  It is
   * called just prior to the info block being released and passes that
   * block to us.  It's function is to update the overrun entry AND to
   * restart the timer.  It should only be called if the timer is to be
   * restarted (i.e. we have flagged this in the sys_private entry of the
   * info block).
   *
25985edce   Lucas De Marchi   Fix common misspe...
292
   * To protect against the timer going away while the interrupt is queued,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
   * we require that the it_requeue_pending flag be set.
   */
ae7795bc6   Eric W. Biederman   signal: Distingui...
295
  void posixtimer_rearm(struct kernel_siginfo *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
  {
  	struct k_itimer *timr;
  	unsigned long flags;
  
  	timr = lock_timer(info->si_tid, &flags);
af888d677   Thomas Gleixner   posix-timers: Uni...
301
302
  	if (!timr)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303

0e334db6b   Thomas Gleixner   posix-timers: Fix...
304
  	if (timr->it_interval && timr->it_requeue_pending == info->si_sys_private) {
f37fb0aa4   Thomas Gleixner   posix-timers: Use...
305
  		timr->kclock->timer_rearm(timr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306

21e55c1f8   Thomas Gleixner   posix-timers: Add...
307
  		timr->it_active = 1;
af888d677   Thomas Gleixner   posix-timers: Uni...
308
  		timr->it_overrun_last = timr->it_overrun;
78c9c4dfb   Thomas Gleixner   posix-timers: San...
309
  		timr->it_overrun = -1LL;
af888d677   Thomas Gleixner   posix-timers: Uni...
310
  		++timr->it_requeue_pending;
78c9c4dfb   Thomas Gleixner   posix-timers: San...
311
  		info->si_overrun = timer_overrun_to_int(timr, info->si_overrun);
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
312
  	}
af888d677   Thomas Gleixner   posix-timers: Uni...
313
  	unlock_timer(timr, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
  }
ba661292a   Oleg Nesterov   posix-timers: fix...
315
  int posix_timer_event(struct k_itimer *timr, int si_private)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
  {
24122c7f4   Eric W. Biederman   signal: Pass pid ...
317
318
  	enum pid_type type;
  	int ret = -1;
ba661292a   Oleg Nesterov   posix-timers: fix...
319
320
  	/*
  	 * FIXME: if ->sigq is queued we can race with
96fe3b072   Thomas Gleixner   posix-timers: Ren...
321
  	 * dequeue_signal()->posixtimer_rearm().
ba661292a   Oleg Nesterov   posix-timers: fix...
322
323
  	 *
  	 * If dequeue_signal() sees the "right" value of
96fe3b072   Thomas Gleixner   posix-timers: Ren...
324
  	 * si_sys_private it calls posixtimer_rearm().
ba661292a   Oleg Nesterov   posix-timers: fix...
325
  	 * We re-queue ->sigq and drop ->it_lock().
96fe3b072   Thomas Gleixner   posix-timers: Ren...
326
  	 * posixtimer_rearm() locks the timer
ba661292a   Oleg Nesterov   posix-timers: fix...
327
328
329
  	 * and re-schedules it while ->sigq is pending.
  	 * Not really bad, but not that we want.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
  	timr->sigq->info.si_sys_private = si_private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331

24122c7f4   Eric W. Biederman   signal: Pass pid ...
332
333
  	type = !(timr->it_sigev_notify & SIGEV_THREAD_ID) ? PIDTYPE_TGID : PIDTYPE_PID;
  	ret = send_sigqueue(timr->sigq, timr->it_pid, type);
4aa736117   Oleg Nesterov   posix-timers: don...
334
335
  	/* If we failed to send the signal the timer stops. */
  	return ret > 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
340
341
342
343
344
  
  /*
   * This function gets called when a POSIX.1b interval timer expires.  It
   * is used as a callback from the kernel internal timer.  The
   * run_timer_list code ALWAYS calls with interrupts on.
  
   * This code is for CLOCK_REALTIME* and CLOCK_MONOTONIC* timers.
   */
c9cb2e3d7   Thomas Gleixner   [PATCH] hrtimers:...
345
  static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  {
05cfb614d   Roman Zippel   [PATCH] hrtimers:...
347
  	struct k_itimer *timr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  	unsigned long flags;
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
349
  	int si_private = 0;
c9cb2e3d7   Thomas Gleixner   [PATCH] hrtimers:...
350
  	enum hrtimer_restart ret = HRTIMER_NORESTART;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351

05cfb614d   Roman Zippel   [PATCH] hrtimers:...
352
  	timr = container_of(timer, struct k_itimer, it.real.timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
  	spin_lock_irqsave(&timr->it_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354

21e55c1f8   Thomas Gleixner   posix-timers: Add...
355
  	timr->it_active = 0;
80105cd0e   Thomas Gleixner   posix-timers: Mov...
356
  	if (timr->it_interval != 0)
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
357
  		si_private = ++timr->it_requeue_pending;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358

becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
359
360
361
362
363
364
  	if (posix_timer_event(timr, si_private)) {
  		/*
  		 * signal was not sent because of sig_ignor
  		 * we will not get a call back to restart it AND
  		 * it should be restarted.
  		 */
80105cd0e   Thomas Gleixner   posix-timers: Mov...
365
  		if (timr->it_interval != 0) {
58229a189   Thomas Gleixner   posix-timers: Pre...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
  			ktime_t now = hrtimer_cb_get_time(timer);
  
  			/*
  			 * FIXME: What we really want, is to stop this
  			 * timer completely and restart it in case the
  			 * SIG_IGN is removed. This is a non trivial
  			 * change which involves sighand locking
  			 * (sigh !), which we don't want to do late in
  			 * the release cycle.
  			 *
  			 * For now we just let timers with an interval
  			 * less than a jiffie expire every jiffie to
  			 * avoid softirq starvation in case of SIG_IGN
  			 * and a very small interval, which would put
  			 * the timer right back on the softirq pending
  			 * list. By moving now ahead of time we trick
  			 * hrtimer_forward() to expire the timer
  			 * later, while we still maintain the overrun
  			 * accuracy, but have some inconsistency in
  			 * the timer_gettime() case. This is at least
  			 * better than a starved softirq. A more
  			 * complex fix which solves also another related
  			 * inconsistency is already in the pipeline.
  			 */
  #ifdef CONFIG_HIGH_RES_TIMERS
  			{
8b0e19531   Thomas Gleixner   ktime: Cleanup kt...
392
  				ktime_t kj = NSEC_PER_SEC / HZ;
58229a189   Thomas Gleixner   posix-timers: Pre...
393

80105cd0e   Thomas Gleixner   posix-timers: Mov...
394
  				if (timr->it_interval < kj)
58229a189   Thomas Gleixner   posix-timers: Pre...
395
396
397
  					now = ktime_add(now, kj);
  			}
  #endif
78c9c4dfb   Thomas Gleixner   posix-timers: San...
398
399
  			timr->it_overrun += hrtimer_forward(timer, now,
  							    timr->it_interval);
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
400
  			ret = HRTIMER_RESTART;
a0a0c28c1   Roman Zippel   [PATCH] posix-tim...
401
  			++timr->it_requeue_pending;
21e55c1f8   Thomas Gleixner   posix-timers: Add...
402
  			timr->it_active = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405

becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
406
407
408
  	unlock_timer(timr, flags);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409

27af4245b   Oleg Nesterov   posix-timers: use...
410
  static struct pid *good_sigevent(sigevent_t * event)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  {
2118e1f53   Eric W. Biederman   posix-timers: Nor...
412
413
  	struct pid *pid = task_tgid(current);
  	struct task_struct *rtn;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414

cef31d9af   Thomas Gleixner   posix-timer: Prop...
415
416
  	switch (event->sigev_notify) {
  	case SIGEV_SIGNAL | SIGEV_THREAD_ID:
2118e1f53   Eric W. Biederman   posix-timers: Nor...
417
418
  		pid = find_vpid(event->sigev_notify_thread_id);
  		rtn = pid_task(pid, PIDTYPE_PID);
cef31d9af   Thomas Gleixner   posix-timer: Prop...
419
420
  		if (!rtn || !same_thread_group(rtn, current))
  			return NULL;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
421
  		fallthrough;
cef31d9af   Thomas Gleixner   posix-timer: Prop...
422
423
424
425
  	case SIGEV_SIGNAL:
  	case SIGEV_THREAD:
  		if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX)
  			return NULL;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
426
  		fallthrough;
cef31d9af   Thomas Gleixner   posix-timer: Prop...
427
  	case SIGEV_NONE:
2118e1f53   Eric W. Biederman   posix-timers: Nor...
428
  		return pid;
cef31d9af   Thomas Gleixner   posix-timer: Prop...
429
  	default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
  		return NULL;
cef31d9af   Thomas Gleixner   posix-timer: Prop...
431
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
  static struct k_itimer * alloc_posix_timer(void)
  {
  	struct k_itimer *tmr;
c37622296   Robert P. J. Day   [PATCH] Transform...
436
  	tmr = kmem_cache_zalloc(posix_timers_cache, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
  	if (!tmr)
  		return tmr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
  	if (unlikely(!(tmr->sigq = sigqueue_alloc()))) {
  		kmem_cache_free(posix_timers_cache, tmr);
aa94fbd5c   Dan Carpenter   fix error-path NU...
441
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
  	}
3b10db2b0   Eric W. Biederman   signal: Replace m...
443
  	clear_siginfo(&tmr->sigq->info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
  	return tmr;
  }
8af088710   Eric Dumazet   posix-timers: RCU...
446
447
  static void k_itimer_rcu_free(struct rcu_head *head)
  {
5d99b32a0   Sebastian Andrzej Siewior   posix-timers: Mov...
448
  	struct k_itimer *tmr = container_of(head, struct k_itimer, rcu);
8af088710   Eric Dumazet   posix-timers: RCU...
449
450
451
  
  	kmem_cache_free(posix_timers_cache, tmr);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
454
455
456
457
  #define IT_ID_SET	1
  #define IT_ID_NOT_SET	0
  static void release_posix_timer(struct k_itimer *tmr, int it_id_set)
  {
  	if (it_id_set) {
  		unsigned long flags;
5ed67f05f   Pavel Emelyanov   posix timers: All...
458
459
460
  		spin_lock_irqsave(&hash_lock, flags);
  		hlist_del_rcu(&tmr->t_hash);
  		spin_unlock_irqrestore(&hash_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
  	}
899921025   Oleg Nesterov   posix-timers: che...
462
  	put_pid(tmr->it_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
  	sigqueue_free(tmr->sigq);
5d99b32a0   Sebastian Andrzej Siewior   posix-timers: Mov...
464
  	call_rcu(&tmr->rcu, k_itimer_rcu_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
  }
838394fbf   Thomas Gleixner   posix-timers: Con...
466
467
468
469
470
  static int common_timer_create(struct k_itimer *new_timer)
  {
  	hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0);
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
  /* Create a POSIX.1b interval timer. */
2482097c6   Al Viro   posix-timers: Mov...
472
473
  static int do_timer_create(clockid_t which_clock, struct sigevent *event,
  			   timer_t __user *created_timer_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
475
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
2cd499e38   Oleg Nesterov   posix-timers: sys...
476
  	struct k_itimer *new_timer;
ef864c958   Oleg Nesterov   posix-timers: sys...
477
  	int error, new_timer_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
  	int it_id_set = IT_ID_NOT_SET;
838394fbf   Thomas Gleixner   posix-timers: Con...
479
  	if (!kc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
  		return -EINVAL;
838394fbf   Thomas Gleixner   posix-timers: Con...
481
482
  	if (!kc->timer_create)
  		return -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
484
485
486
487
488
  
  	new_timer = alloc_posix_timer();
  	if (unlikely(!new_timer))
  		return -EAGAIN;
  
  	spin_lock_init(&new_timer->it_lock);
5ed67f05f   Pavel Emelyanov   posix timers: All...
489
490
491
  	new_timer_id = posix_timer_add(new_timer);
  	if (new_timer_id < 0) {
  		error = new_timer_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
494
495
496
497
  		goto out;
  	}
  
  	it_id_set = IT_ID_SET;
  	new_timer->it_id = (timer_t) new_timer_id;
  	new_timer->it_clock = which_clock;
d97bb75dd   Thomas Gleixner   posix-timers: Sto...
498
  	new_timer->kclock = kc;
78c9c4dfb   Thomas Gleixner   posix-timers: San...
499
  	new_timer->it_overrun = -1LL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500

2482097c6   Al Viro   posix-timers: Mov...
501
  	if (event) {
36b2f0460   Oleg Nesterov   posix-timers: sys...
502
  		rcu_read_lock();
2482097c6   Al Viro   posix-timers: Mov...
503
  		new_timer->it_pid = get_pid(good_sigevent(event));
36b2f0460   Oleg Nesterov   posix-timers: sys...
504
  		rcu_read_unlock();
899921025   Oleg Nesterov   posix-timers: che...
505
  		if (!new_timer->it_pid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
  			error = -EINVAL;
  			goto out;
  		}
2482097c6   Al Viro   posix-timers: Mov...
509
510
511
  		new_timer->it_sigev_notify     = event->sigev_notify;
  		new_timer->sigq->info.si_signo = event->sigev_signo;
  		new_timer->sigq->info.si_value = event->sigev_value;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
  	} else {
2482097c6   Al Viro   posix-timers: Mov...
513
514
515
516
  		new_timer->it_sigev_notify     = SIGEV_SIGNAL;
  		new_timer->sigq->info.si_signo = SIGALRM;
  		memset(&new_timer->sigq->info.si_value, 0, sizeof(sigval_t));
  		new_timer->sigq->info.si_value.sival_int = new_timer->it_id;
899921025   Oleg Nesterov   posix-timers: che...
517
  		new_timer->it_pid = get_pid(task_tgid(current));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
  	}
717835d94   Oleg Nesterov   posix-timers: mov...
519
  	new_timer->sigq->info.si_tid   = new_timer->it_id;
5a9fa7307   Oleg Nesterov   posix-timers: kil...
520
  	new_timer->sigq->info.si_code  = SI_TIMER;
717835d94   Oleg Nesterov   posix-timers: mov...
521

2b08de007   Andrey Vagin   posix_timer: Move...
522
523
524
525
526
  	if (copy_to_user(created_timer_id,
  			 &new_timer_id, sizeof (new_timer_id))) {
  		error = -EFAULT;
  		goto out;
  	}
838394fbf   Thomas Gleixner   posix-timers: Con...
527
  	error = kc->timer_create(new_timer);
45e0fffc8   Andrey Vagin   posix_timer: Fix ...
528
529
  	if (error)
  		goto out;
36b2f0460   Oleg Nesterov   posix-timers: sys...
530
  	spin_lock_irq(&current->sighand->siglock);
27af4245b   Oleg Nesterov   posix-timers: use...
531
  	new_timer->it_signal = current->signal;
36b2f0460   Oleg Nesterov   posix-timers: sys...
532
533
  	list_add(&new_timer->list, &current->signal->posix_timers);
  	spin_unlock_irq(&current->sighand->siglock);
ef864c958   Oleg Nesterov   posix-timers: sys...
534
535
  
  	return 0;
838394fbf   Thomas Gleixner   posix-timers: Con...
536
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
540
541
  	 * In the case of the timer belonging to another task, after
  	 * the task is unlocked, the timer is owned by the other task
  	 * and may cease to exist at any time.  Don't use or modify
  	 * new_timer after the unlock call.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
  out:
ef864c958   Oleg Nesterov   posix-timers: sys...
543
  	release_posix_timer(new_timer, it_id_set);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
  	return error;
  }
2482097c6   Al Viro   posix-timers: Mov...
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
  		struct sigevent __user *, timer_event_spec,
  		timer_t __user *, created_timer_id)
  {
  	if (timer_event_spec) {
  		sigevent_t event;
  
  		if (copy_from_user(&event, timer_event_spec, sizeof (event)))
  			return -EFAULT;
  		return do_timer_create(which_clock, &event, created_timer_id);
  	}
  	return do_timer_create(which_clock, NULL, created_timer_id);
  }
  
  #ifdef CONFIG_COMPAT
  COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
  		       struct compat_sigevent __user *, timer_event_spec,
  		       timer_t __user *, created_timer_id)
  {
  	if (timer_event_spec) {
  		sigevent_t event;
  
  		if (get_compat_sigevent(&event, timer_event_spec))
  			return -EFAULT;
  		return do_timer_create(which_clock, &event, created_timer_id);
  	}
  	return do_timer_create(which_clock, NULL, created_timer_id);
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
578
579
580
581
   * Locking issues: We need to protect the result of the id look up until
   * we get the timer locked down so it is not deleted under us.  The
   * removal is done under the idr spinlock so we use that here to bridge
   * the find to the timer lock.  To avoid a dead lock, the timer id MUST
   * be release with out holding the timer lock.
   */
20f33a03f   Namhyung Kim   posix-timers: Ann...
582
  static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
  {
  	struct k_itimer *timr;
8af088710   Eric Dumazet   posix-timers: RCU...
585

e182bb38d   Tejun Heo   posix-timer: Don'...
586
587
588
589
590
591
  	/*
  	 * timer_t could be any type >= int and we want to make sure any
  	 * @timer_id outside positive int range fails lookup.
  	 */
  	if ((unsigned long long)timer_id > INT_MAX)
  		return NULL;
8af088710   Eric Dumazet   posix-timers: RCU...
592
  	rcu_read_lock();
5ed67f05f   Pavel Emelyanov   posix timers: All...
593
  	timr = posix_timer_by_id(timer_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
  	if (timr) {
8af088710   Eric Dumazet   posix-timers: RCU...
595
  		spin_lock_irqsave(&timr->it_lock, *flags);
899921025   Oleg Nesterov   posix-timers: che...
596
  		if (timr->it_signal == current->signal) {
8af088710   Eric Dumazet   posix-timers: RCU...
597
  			rcu_read_unlock();
31d928456   Oleg Nesterov   posix-timers: loc...
598
599
  			return timr;
  		}
8af088710   Eric Dumazet   posix-timers: RCU...
600
  		spin_unlock_irqrestore(&timr->it_lock, *flags);
31d928456   Oleg Nesterov   posix-timers: loc...
601
  	}
8af088710   Eric Dumazet   posix-timers: RCU...
602
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603

31d928456   Oleg Nesterov   posix-timers: loc...
604
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  }
91d57bae0   Thomas Gleixner   posix-timers: Mak...
606
607
608
609
610
611
  static ktime_t common_hrtimer_remaining(struct k_itimer *timr, ktime_t now)
  {
  	struct hrtimer *timer = &timr->it.real.timer;
  
  	return __hrtimer_expires_remaining_adjusted(timer, now);
  }
6fec64e1c   Thomas Gleixner   posix-timers: Mak...
612
  static s64 common_hrtimer_forward(struct k_itimer *timr, ktime_t now)
91d57bae0   Thomas Gleixner   posix-timers: Mak...
613
614
  {
  	struct hrtimer *timer = &timr->it.real.timer;
6fec64e1c   Thomas Gleixner   posix-timers: Mak...
615
  	return hrtimer_forward(timer, now, timr->it_interval);
91d57bae0   Thomas Gleixner   posix-timers: Mak...
616
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
  /*
   * Get the time remaining on a POSIX.1b interval timer.  This function
   * is ALWAYS called with spin_lock_irq on the timer, thus it must not
   * mess with irq.
   *
   * We have a couple of messes to clean up here.  First there is the case
   * of a timer that has a requeue pending.  These timers should appear to
   * be in the timer list with an expiry as if we were to requeue them
   * now.
   *
   * The second issue is the SIGEV_NONE timer which may be active but is
   * not really ever put in the timer list (to save system resources).
   * This timer may be expired, and if so, we will do it here.  Otherwise
   * it is the same as a requeue pending timer WRT to what we should
   * report.
   */
f2c45807d   Thomas Gleixner   alarmtimer: Switc...
633
  void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
  {
91d57bae0   Thomas Gleixner   posix-timers: Mak...
635
  	const struct k_clock *kc = timr->kclock;
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
636
  	ktime_t now, remaining, iv;
91d57bae0   Thomas Gleixner   posix-timers: Mak...
637
  	bool sig_none;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638

cef31d9af   Thomas Gleixner   posix-timer: Prop...
639
  	sig_none = timr->it_sigev_notify == SIGEV_NONE;
80105cd0e   Thomas Gleixner   posix-timers: Mov...
640
  	iv = timr->it_interval;
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
641

becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
642
  	/* interval timer ? */
91d57bae0   Thomas Gleixner   posix-timers: Mak...
643
  	if (iv) {
5f252b325   Deepa Dinamani   time: Change k_cl...
644
  		cur_setting->it_interval = ktime_to_timespec64(iv);
91d57bae0   Thomas Gleixner   posix-timers: Mak...
645
646
647
648
649
650
651
652
  	} else if (!timr->it_active) {
  		/*
  		 * SIGEV_NONE oneshot timers are never queued. Check them
  		 * below.
  		 */
  		if (!sig_none)
  			return;
  	}
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
653

198fa445d   Andrei Vagin   posix-timers: Use...
654
  	now = kc->clock_get_ktime(timr->it_clock);
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
655

becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
656
  	/*
91d57bae0   Thomas Gleixner   posix-timers: Mak...
657
658
  	 * When a requeue is pending or this is a SIGEV_NONE timer move the
  	 * expiry time forward by intervals, so expiry is > now.
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
659
  	 */
91d57bae0   Thomas Gleixner   posix-timers: Mak...
660
  	if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none))
78c9c4dfb   Thomas Gleixner   posix-timers: San...
661
  		timr->it_overrun += kc->timer_forward(timr, now);
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
662

91d57bae0   Thomas Gleixner   posix-timers: Mak...
663
  	remaining = kc->timer_remaining(timr, now);
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
664
  	/* Return 0 only, when the timer is expired and not pending */
2456e8553   Thomas Gleixner   ktime: Get rid of...
665
  	if (remaining <= 0) {
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
666
667
668
669
  		/*
  		 * A single shot SIGEV_NONE timer must return 0, when
  		 * it is expired !
  		 */
91d57bae0   Thomas Gleixner   posix-timers: Mak...
670
  		if (!sig_none)
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
671
  			cur_setting->it_value.tv_nsec = 1;
91d57bae0   Thomas Gleixner   posix-timers: Mak...
672
  	} else {
5f252b325   Deepa Dinamani   time: Change k_cl...
673
  		cur_setting->it_value = ktime_to_timespec64(remaining);
91d57bae0   Thomas Gleixner   posix-timers: Mak...
674
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
677
  }
  
  /* Get the time remaining on a POSIX.1b interval timer. */
b0dc12426   Al Viro   posix-timers: Tak...
678
  static int do_timer_gettime(timer_t timer_id,  struct itimerspec64 *setting)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
  {
a7319fa25   Thomas Gleixner   posix-timers: Con...
680
  	struct k_itimer *timr;
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
681
  	const struct k_clock *kc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
  	unsigned long flags;
a7319fa25   Thomas Gleixner   posix-timers: Con...
683
  	int ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
684
685
686
687
  
  	timr = lock_timer(timer_id, &flags);
  	if (!timr)
  		return -EINVAL;
b0dc12426   Al Viro   posix-timers: Tak...
688
  	memset(setting, 0, sizeof(*setting));
d97bb75dd   Thomas Gleixner   posix-timers: Sto...
689
  	kc = timr->kclock;
a7319fa25   Thomas Gleixner   posix-timers: Con...
690
691
692
  	if (WARN_ON_ONCE(!kc || !kc->timer_get))
  		ret = -EINVAL;
  	else
b0dc12426   Al Viro   posix-timers: Tak...
693
  		kc->timer_get(timr, setting);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
694
695
  
  	unlock_timer(timr, flags);
b0dc12426   Al Viro   posix-timers: Tak...
696
697
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698

b0dc12426   Al Viro   posix-timers: Tak...
699
700
  /* Get the time remaining on a POSIX.1b interval timer. */
  SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
6ff847350   Deepa Dinamani   time: Change type...
701
  		struct __kernel_itimerspec __user *, setting)
b0dc12426   Al Viro   posix-timers: Tak...
702
  {
725816e8a   Deepa Dinamani   posix_clocks: Use...
703
  	struct itimerspec64 cur_setting;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704

725816e8a   Deepa Dinamani   posix_clocks: Use...
705
  	int ret = do_timer_gettime(timer_id, &cur_setting);
b0dc12426   Al Viro   posix-timers: Tak...
706
  	if (!ret) {
725816e8a   Deepa Dinamani   posix_clocks: Use...
707
  		if (put_itimerspec64(&cur_setting, setting))
b0dc12426   Al Viro   posix-timers: Tak...
708
709
  			ret = -EFAULT;
  	}
a7319fa25   Thomas Gleixner   posix-timers: Con...
710
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
  }
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
712

6ff847350   Deepa Dinamani   time: Change type...
713
  #ifdef CONFIG_COMPAT_32BIT_TIME
8dabe7245   Arnd Bergmann   y2038: syscalls: ...
714
715
  SYSCALL_DEFINE2(timer_gettime32, timer_t, timer_id,
  		struct old_itimerspec32 __user *, setting)
b0dc12426   Al Viro   posix-timers: Tak...
716
  {
725816e8a   Deepa Dinamani   posix_clocks: Use...
717
  	struct itimerspec64 cur_setting;
b0dc12426   Al Viro   posix-timers: Tak...
718

725816e8a   Deepa Dinamani   posix_clocks: Use...
719
  	int ret = do_timer_gettime(timer_id, &cur_setting);
b0dc12426   Al Viro   posix-timers: Tak...
720
  	if (!ret) {
9afc5eee6   Arnd Bergmann   y2038: globally r...
721
  		if (put_old_itimerspec32(&cur_setting, setting))
b0dc12426   Al Viro   posix-timers: Tak...
722
723
724
725
  			ret = -EFAULT;
  	}
  	return ret;
  }
6ff847350   Deepa Dinamani   time: Change type...
726

b0dc12426   Al Viro   posix-timers: Tak...
727
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
730
731
732
733
  /*
   * Get the number of overruns of a POSIX.1b interval timer.  This is to
   * be the overrun of the timer last delivered.  At the same time we are
   * accumulating overruns on the next timer.  The overrun is frozen when
   * the signal is delivered, either at the notify time (if the info block
   * is not queued) or at the actual delivery time (as we are informed by
96fe3b072   Thomas Gleixner   posix-timers: Ren...
734
   * the call back to posixtimer_rearm().  So all we need to do is
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
736
   * to pick up the frozen overrun.
   */
362e9c07c   Heiko Carstens   [CVE-2009-0029] S...
737
  SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
739
740
  {
  	struct k_itimer *timr;
  	int overrun;
5ba253313   Al Viro   more low-hanging ...
741
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
745
  
  	timr = lock_timer(timer_id, &flags);
  	if (!timr)
  		return -EINVAL;
78c9c4dfb   Thomas Gleixner   posix-timers: San...
746
  	overrun = timer_overrun_to_int(timr, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747
748
749
750
  	unlock_timer(timr, flags);
  
  	return overrun;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751

eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
752
753
754
755
756
757
758
  static void common_hrtimer_arm(struct k_itimer *timr, ktime_t expires,
  			       bool absolute, bool sigev_none)
  {
  	struct hrtimer *timer = &timr->it.real.timer;
  	enum hrtimer_mode mode;
  
  	mode = absolute ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL;
67edab48c   Thomas Gleixner   posix-timers: Han...
759
760
761
762
  	/*
  	 * Posix magic: Relative CLOCK_REALTIME timers are not affected by
  	 * clock modifications, so they become CLOCK_MONOTONIC based under the
  	 * hood. See hrtimer_init(). Update timr->kclock, so the generic
9c71a2e8a   Andrei Vagin   posix-clocks: Int...
763
  	 * functions which use timr->kclock->clock_get_*() work.
67edab48c   Thomas Gleixner   posix-timers: Han...
764
765
766
767
768
769
  	 *
  	 * Note: it_clock stays unmodified, because the next timer_set() might
  	 * use ABSTIME, so it needs to switch back.
  	 */
  	if (timr->it_clock == CLOCK_REALTIME)
  		timr->kclock = absolute ? &clock_realtime : &clock_monotonic;
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  	hrtimer_init(&timr->it.real.timer, timr->it_clock, mode);
  	timr->it.real.timer.function = posix_timer_fn;
  
  	if (!absolute)
  		expires = ktime_add_safe(expires, timer->base->get_time());
  	hrtimer_set_expires(timer, expires);
  
  	if (!sigev_none)
  		hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
  }
  
  static int common_hrtimer_try_to_cancel(struct k_itimer *timr)
  {
  	return hrtimer_try_to_cancel(&timr->it.real.timer);
  }
ec8f954a4   Thomas Gleixner   posix-timers: Use...
785
786
787
788
  static void common_timer_wait_running(struct k_itimer *timer)
  {
  	hrtimer_cancel_wait_running(&timer->it.real.timer);
  }
0bee3b601   Frederic Weisbecker   hrtimer: Improve ...
789
790
791
792
793
794
  /*
   * On PREEMPT_RT this prevent priority inversion against softirq kthread in
   * case it gets preempted while executing a timer callback. See comments in
   * hrtimer_cancel_wait_running. For PREEMPT_RT=n this just results in a
   * cpu_relax().
   */
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
795
796
797
  static struct k_itimer *timer_wait_running(struct k_itimer *timer,
  					   unsigned long *flags)
  {
ec8f954a4   Thomas Gleixner   posix-timers: Use...
798
  	const struct k_clock *kc = READ_ONCE(timer->kclock);
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
799
  	timer_t timer_id = READ_ONCE(timer->it_id);
ec8f954a4   Thomas Gleixner   posix-timers: Use...
800
801
  	/* Prevent kfree(timer) after dropping the lock */
  	rcu_read_lock();
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
802
  	unlock_timer(timer, *flags);
ec8f954a4   Thomas Gleixner   posix-timers: Use...
803
804
805
806
807
  
  	if (!WARN_ON_ONCE(!kc->timer_wait_running))
  		kc->timer_wait_running(timer);
  
  	rcu_read_unlock();
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
808
809
810
  	/* Relock the timer. It might be not longer hashed. */
  	return lock_timer(timer_id, flags);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
  /* Set a POSIX.1b interval timer. */
f2c45807d   Thomas Gleixner   alarmtimer: Switc...
812
813
814
  int common_timer_set(struct k_itimer *timr, int flags,
  		     struct itimerspec64 *new_setting,
  		     struct itimerspec64 *old_setting)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
  {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
816
817
818
  	const struct k_clock *kc = timr->kclock;
  	bool sigev_none;
  	ktime_t expires;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
820
821
  
  	if (old_setting)
  		common_timer_get(timr, old_setting);
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
822
  	/* Prevent rearming by clearing the interval */
80105cd0e   Thomas Gleixner   posix-timers: Mov...
823
  	timr->it_interval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  	/*
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
825
826
  	 * Careful here. On SMP systems the timer expiry function could be
  	 * active and spinning on timr->it_lock.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
  	 */
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
828
  	if (kc->timer_try_to_cancel(timr) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
  		return TIMER_RETRY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830

21e55c1f8   Thomas Gleixner   posix-timers: Add...
831
832
  	timr->it_active = 0;
  	timr->it_requeue_pending = (timr->it_requeue_pending + 2) &
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
834
  		~REQUEUE_PENDING;
  	timr->it_overrun_last = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835

eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
836
  	/* Switch off the timer when it_value is zero */
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
837
838
  	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
839

80105cd0e   Thomas Gleixner   posix-timers: Mov...
840
  	timr->it_interval = timespec64_to_ktime(new_setting->it_interval);
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
841
  	expires = timespec64_to_ktime(new_setting->it_value);
7da8b3a44   Andrei Vagin   posix-timers: Mak...
842
843
  	if (flags & TIMER_ABSTIME)
  		expires = timens_ktime_to_host(timr->it_clock, expires);
cef31d9af   Thomas Gleixner   posix-timer: Prop...
844
  	sigev_none = timr->it_sigev_notify == SIGEV_NONE;
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
845

eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
846
847
  	kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none);
  	timr->it_active = !sigev_none;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
849
  	return 0;
  }
21670ee44   Thomas Gleixner   posix-timers: Cle...
850
  static int do_timer_settime(timer_t timer_id, int tmr_flags,
1acbe7708   Al Viro   posix-timers: Tak...
851
852
  			    struct itimerspec64 *new_spec64,
  			    struct itimerspec64 *old_spec64)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853
  {
1acbe7708   Al Viro   posix-timers: Tak...
854
  	const struct k_clock *kc;
5f252b325   Deepa Dinamani   time: Change k_cl...
855
  	struct k_itimer *timr;
21670ee44   Thomas Gleixner   posix-timers: Cle...
856
  	unsigned long flags;
5f252b325   Deepa Dinamani   time: Change k_cl...
857
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858

1acbe7708   Al Viro   posix-timers: Tak...
859
860
  	if (!timespec64_valid(&new_spec64->it_interval) ||
  	    !timespec64_valid(&new_spec64->it_value))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
  		return -EINVAL;
1acbe7708   Al Viro   posix-timers: Tak...
862
863
  	if (old_spec64)
  		memset(old_spec64, 0, sizeof(*old_spec64));
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
864

21670ee44   Thomas Gleixner   posix-timers: Cle...
865
  	timr = lock_timer(timer_id, &flags);
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
866
  retry:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
  	if (!timr)
  		return -EINVAL;
d97bb75dd   Thomas Gleixner   posix-timers: Sto...
869
  	kc = timr->kclock;
27722df16   Thomas Gleixner   posix-timers: Con...
870
871
872
  	if (WARN_ON_ONCE(!kc || !kc->timer_set))
  		error = -EINVAL;
  	else
21670ee44   Thomas Gleixner   posix-timers: Cle...
873
  		error = kc->timer_set(timr, tmr_flags, new_spec64, old_spec64);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
  	if (error == TIMER_RETRY) {
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
876
877
878
879
  		// We already got the old time...
  		old_spec64 = NULL;
  		/* Unlocks and relocks the timer if it still exists */
  		timr = timer_wait_running(timr, &flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
880
881
  		goto retry;
  	}
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
882
  	unlock_timer(timr, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883

1acbe7708   Al Viro   posix-timers: Tak...
884
885
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886

1acbe7708   Al Viro   posix-timers: Tak...
887
888
  /* Set a POSIX.1b interval timer */
  SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
6ff847350   Deepa Dinamani   time: Change type...
889
890
  		const struct __kernel_itimerspec __user *, new_setting,
  		struct __kernel_itimerspec __user *, old_setting)
1acbe7708   Al Viro   posix-timers: Tak...
891
  {
725816e8a   Deepa Dinamani   posix_clocks: Use...
892
893
  	struct itimerspec64 new_spec, old_spec;
  	struct itimerspec64 *rtn = old_setting ? &old_spec : NULL;
1acbe7708   Al Viro   posix-timers: Tak...
894
895
896
897
  	int error = 0;
  
  	if (!new_setting)
  		return -EINVAL;
725816e8a   Deepa Dinamani   posix_clocks: Use...
898
  	if (get_itimerspec64(&new_spec, new_setting))
1acbe7708   Al Viro   posix-timers: Tak...
899
  		return -EFAULT;
1acbe7708   Al Viro   posix-timers: Tak...
900

725816e8a   Deepa Dinamani   posix_clocks: Use...
901
  	error = do_timer_settime(timer_id, flags, &new_spec, rtn);
1acbe7708   Al Viro   posix-timers: Tak...
902
  	if (!error && old_setting) {
725816e8a   Deepa Dinamani   posix_clocks: Use...
903
  		if (put_itimerspec64(&old_spec, old_setting))
1acbe7708   Al Viro   posix-timers: Tak...
904
905
906
907
  			error = -EFAULT;
  	}
  	return error;
  }
6ff847350   Deepa Dinamani   time: Change type...
908
  #ifdef CONFIG_COMPAT_32BIT_TIME
8dabe7245   Arnd Bergmann   y2038: syscalls: ...
909
910
911
  SYSCALL_DEFINE4(timer_settime32, timer_t, timer_id, int, flags,
  		struct old_itimerspec32 __user *, new,
  		struct old_itimerspec32 __user *, old)
1acbe7708   Al Viro   posix-timers: Tak...
912
  {
725816e8a   Deepa Dinamani   posix_clocks: Use...
913
914
  	struct itimerspec64 new_spec, old_spec;
  	struct itimerspec64 *rtn = old ? &old_spec : NULL;
1acbe7708   Al Viro   posix-timers: Tak...
915
916
917
918
  	int error = 0;
  
  	if (!new)
  		return -EINVAL;
9afc5eee6   Arnd Bergmann   y2038: globally r...
919
  	if (get_old_itimerspec32(&new_spec, new))
1acbe7708   Al Viro   posix-timers: Tak...
920
  		return -EFAULT;
725816e8a   Deepa Dinamani   posix_clocks: Use...
921
  	error = do_timer_settime(timer_id, flags, &new_spec, rtn);
1acbe7708   Al Viro   posix-timers: Tak...
922
  	if (!error && old) {
9afc5eee6   Arnd Bergmann   y2038: globally r...
923
  		if (put_old_itimerspec32(&old_spec, old))
1acbe7708   Al Viro   posix-timers: Tak...
924
925
  			error = -EFAULT;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
927
  	return error;
  }
1acbe7708   Al Viro   posix-timers: Tak...
928
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929

f2c45807d   Thomas Gleixner   alarmtimer: Switc...
930
  int common_timer_del(struct k_itimer *timer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
  {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
932
  	const struct k_clock *kc = timer->kclock;
f972be33c   Oleg Nesterov   [PATCH] posix-tim...
933

eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
934
935
  	timer->it_interval = 0;
  	if (kc->timer_try_to_cancel(timer) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
  		return TIMER_RETRY;
21e55c1f8   Thomas Gleixner   posix-timers: Add...
937
  	timer->it_active = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
939
940
941
942
  	return 0;
  }
  
  static inline int timer_delete_hook(struct k_itimer *timer)
  {
d97bb75dd   Thomas Gleixner   posix-timers: Sto...
943
  	const struct k_clock *kc = timer->kclock;
6761c6702   Thomas Gleixner   posix-timers: Con...
944
945
946
947
  
  	if (WARN_ON_ONCE(!kc || !kc->timer_del))
  		return -EINVAL;
  	return kc->timer_del(timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948
949
950
  }
  
  /* Delete a POSIX.1b interval timer. */
362e9c07c   Heiko Carstens   [CVE-2009-0029] S...
951
  SYSCALL_DEFINE1(timer_delete, timer_t, timer_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
  {
  	struct k_itimer *timer;
5ba253313   Al Viro   more low-hanging ...
954
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
  	timer = lock_timer(timer_id, &flags);
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
957
958
  
  retry_delete:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
960
  	if (!timer)
  		return -EINVAL;
6945e5c2a   Thomas Gleixner   posix-timers: Rew...
961
962
963
  	if (unlikely(timer_delete_hook(timer) == TIMER_RETRY)) {
  		/* Unlocks and relocks the timer if it still exists */
  		timer = timer_wait_running(timer, &flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
965
  		goto retry_delete;
  	}
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
966

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
968
969
970
971
972
973
  	spin_lock(&current->sighand->siglock);
  	list_del(&timer->list);
  	spin_unlock(&current->sighand->siglock);
  	/*
  	 * This keeps any tasks waiting on the spin lock from thinking
  	 * they got something (see the lock code above).
  	 */
899921025   Oleg Nesterov   posix-timers: che...
974
  	timer->it_signal = NULL;
4b7a13042   Oleg Nesterov   posix timers: tim...
975

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
977
978
979
  	unlock_timer(timer, flags);
  	release_posix_timer(timer, IT_ID_SET);
  	return 0;
  }
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
980

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
982
983
  /*
   * return timer owned by the process, used by exit_itimers
   */
858119e15   Arjan van de Ven   [PATCH] Unlinline...
984
  static void itimer_delete(struct k_itimer *timer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986
  retry_delete:
7586addb9   Sebastian Andrzej Siewior   posix-timers: Use...
987
  	spin_lock_irq(&timer->it_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
988

becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
989
  	if (timer_delete_hook(timer) == TIMER_RETRY) {
7586addb9   Sebastian Andrzej Siewior   posix-timers: Use...
990
  		spin_unlock_irq(&timer->it_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
991
992
  		goto retry_delete;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
  	list_del(&timer->list);
4b7a13042   Oleg Nesterov   posix timers: tim...
994

7586addb9   Sebastian Andrzej Siewior   posix-timers: Use...
995
  	spin_unlock_irq(&timer->it_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
997
998
999
  	release_posix_timer(timer, IT_ID_SET);
  }
  
  /*
25f407f0b   Roland McGrath   [PATCH] Call exit...
1000
   * This is called by do_exit or de_thread, only when there are no more
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
   * references to the shared signal_struct.
   */
  void exit_itimers(struct signal_struct *sig)
  {
  	struct k_itimer *tmr;
  
  	while (!list_empty(&sig->posix_timers)) {
  		tmr = list_entry(sig->posix_timers.next, struct k_itimer, list);
  		itimer_delete(tmr);
  	}
  }
362e9c07c   Heiko Carstens   [CVE-2009-0029] S...
1012
  SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
6d5b84132   Deepa Dinamani   time: Change type...
1013
  		const struct __kernel_timespec __user *, tp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1015
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1016
  	struct timespec64 new_tp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017

26f9a4796   Thomas Gleixner   posix-timers: Con...
1018
  	if (!kc || !kc->clock_set)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  		return -EINVAL;
26f9a4796   Thomas Gleixner   posix-timers: Con...
1020

5c4994102   Deepa Dinamani   posix-timers: Use...
1021
  	if (get_timespec64(&new_tp, tp))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
  		return -EFAULT;
5c4994102   Deepa Dinamani   posix-timers: Use...
1023
  	return kc->clock_set(which_clock, &new_tp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
  }
362e9c07c   Heiko Carstens   [CVE-2009-0029] S...
1025
  SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
6d5b84132   Deepa Dinamani   time: Change type...
1026
  		struct __kernel_timespec __user *, tp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1028
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1029
  	struct timespec64 kernel_tp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
  	int error;
422857776   Thomas Gleixner   posix-timers: Con...
1031
  	if (!kc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
  		return -EINVAL;
422857776   Thomas Gleixner   posix-timers: Con...
1033

819a95fe3   Andrei Vagin   posix-clocks: Ren...
1034
  	error = kc->clock_get_timespec(which_clock, &kernel_tp);
422857776   Thomas Gleixner   posix-timers: Con...
1035

5c4994102   Deepa Dinamani   posix-timers: Use...
1036
  	if (!error && put_timespec64(&kernel_tp, tp))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1037
1038
1039
  		error = -EFAULT;
  
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
  }
ead25417f   Deepa Dinamani   timex: use __kern...
1041
  int do_clock_adjtime(const clockid_t which_clock, struct __kernel_timex * ktx)
f1f1d5ebd   Richard Cochran   posix-timers: Int...
1042
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1043
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
f1f1d5ebd   Richard Cochran   posix-timers: Int...
1044
1045
1046
1047
1048
  
  	if (!kc)
  		return -EINVAL;
  	if (!kc->clock_adj)
  		return -EOPNOTSUPP;
1a596398a   Arnd Bergmann   sparc64: add cust...
1049
1050
1051
1052
  	return kc->clock_adj(which_clock, ktx);
  }
  
  SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
3876ced47   Deepa Dinamani   timex: change sys...
1053
  		struct __kernel_timex __user *, utx)
1a596398a   Arnd Bergmann   sparc64: add cust...
1054
  {
ead25417f   Deepa Dinamani   timex: use __kern...
1055
  	struct __kernel_timex ktx;
1a596398a   Arnd Bergmann   sparc64: add cust...
1056
  	int err;
f1f1d5ebd   Richard Cochran   posix-timers: Int...
1057
1058
  	if (copy_from_user(&ktx, utx, sizeof(ktx)))
  		return -EFAULT;
1a596398a   Arnd Bergmann   sparc64: add cust...
1059
  	err = do_clock_adjtime(which_clock, &ktx);
f1f1d5ebd   Richard Cochran   posix-timers: Int...
1060

f0dbe81f0   Miroslav Lichvar   posix-timers: Fix...
1061
  	if (err >= 0 && copy_to_user(utx, &ktx, sizeof(ktx)))
f1f1d5ebd   Richard Cochran   posix-timers: Int...
1062
1063
1064
1065
  		return -EFAULT;
  
  	return err;
  }
d822cdcce   Al Viro   posix-timers: Mov...
1066
  SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
6d5b84132   Deepa Dinamani   time: Change type...
1067
  		struct __kernel_timespec __user *, tp)
d822cdcce   Al Viro   posix-timers: Mov...
1068
1069
  {
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1070
  	struct timespec64 rtn_tp;
d822cdcce   Al Viro   posix-timers: Mov...
1071
1072
1073
1074
  	int error;
  
  	if (!kc)
  		return -EINVAL;
5c4994102   Deepa Dinamani   posix-timers: Use...
1075
  	error = kc->clock_getres(which_clock, &rtn_tp);
d822cdcce   Al Viro   posix-timers: Mov...
1076

5c4994102   Deepa Dinamani   posix-timers: Use...
1077
  	if (!error && tp && put_timespec64(&rtn_tp, tp))
d822cdcce   Al Viro   posix-timers: Mov...
1078
1079
1080
1081
  		error = -EFAULT;
  
  	return error;
  }
b5793b0d9   Deepa Dinamani   posix-timers: Mak...
1082
  #ifdef CONFIG_COMPAT_32BIT_TIME
3a4d44b61   Al Viro   ntp: Move adjtime...
1083

8dabe7245   Arnd Bergmann   y2038: syscalls: ...
1084
1085
  SYSCALL_DEFINE2(clock_settime32, clockid_t, which_clock,
  		struct old_timespec32 __user *, tp)
d822cdcce   Al Viro   posix-timers: Mov...
1086
1087
  {
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1088
  	struct timespec64 ts;
d822cdcce   Al Viro   posix-timers: Mov...
1089
1090
1091
  
  	if (!kc || !kc->clock_set)
  		return -EINVAL;
9afc5eee6   Arnd Bergmann   y2038: globally r...
1092
  	if (get_old_timespec32(&ts, tp))
d822cdcce   Al Viro   posix-timers: Mov...
1093
  		return -EFAULT;
5c4994102   Deepa Dinamani   posix-timers: Use...
1094
  	return kc->clock_set(which_clock, &ts);
d822cdcce   Al Viro   posix-timers: Mov...
1095
  }
8dabe7245   Arnd Bergmann   y2038: syscalls: ...
1096
1097
  SYSCALL_DEFINE2(clock_gettime32, clockid_t, which_clock,
  		struct old_timespec32 __user *, tp)
d822cdcce   Al Viro   posix-timers: Mov...
1098
1099
  {
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1100
1101
  	struct timespec64 ts;
  	int err;
d822cdcce   Al Viro   posix-timers: Mov...
1102
1103
1104
  
  	if (!kc)
  		return -EINVAL;
819a95fe3   Andrei Vagin   posix-clocks: Ren...
1105
  	err = kc->clock_get_timespec(which_clock, &ts);
d822cdcce   Al Viro   posix-timers: Mov...
1106

9afc5eee6   Arnd Bergmann   y2038: globally r...
1107
  	if (!err && put_old_timespec32(&ts, tp))
5c4994102   Deepa Dinamani   posix-timers: Use...
1108
  		err = -EFAULT;
d822cdcce   Al Viro   posix-timers: Mov...
1109

5c4994102   Deepa Dinamani   posix-timers: Use...
1110
  	return err;
d822cdcce   Al Viro   posix-timers: Mov...
1111
  }
8dabe7245   Arnd Bergmann   y2038: syscalls: ...
1112
1113
  SYSCALL_DEFINE2(clock_adjtime32, clockid_t, which_clock,
  		struct old_timex32 __user *, utp)
3a4d44b61   Al Viro   ntp: Move adjtime...
1114
  {
ead25417f   Deepa Dinamani   timex: use __kern...
1115
  	struct __kernel_timex ktx;
3a4d44b61   Al Viro   ntp: Move adjtime...
1116
  	int err;
4d5f007ee   Arnd Bergmann   time: make adjtim...
1117
  	err = get_old_timex32(&ktx, utp);
3a4d44b61   Al Viro   ntp: Move adjtime...
1118
1119
  	if (err)
  		return err;
1a596398a   Arnd Bergmann   sparc64: add cust...
1120
  	err = do_clock_adjtime(which_clock, &ktx);
3a4d44b61   Al Viro   ntp: Move adjtime...
1121
1122
  
  	if (err >= 0)
4d5f007ee   Arnd Bergmann   time: make adjtim...
1123
  		err = put_old_timex32(utp, &ktx);
3a4d44b61   Al Viro   ntp: Move adjtime...
1124
1125
1126
  
  	return err;
  }
3a4d44b61   Al Viro   ntp: Move adjtime...
1127

8dabe7245   Arnd Bergmann   y2038: syscalls: ...
1128
1129
  SYSCALL_DEFINE2(clock_getres_time32, clockid_t, which_clock,
  		struct old_timespec32 __user *, tp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1131
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1132
1133
  	struct timespec64 ts;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134

e5e542eea   Thomas Gleixner   posix-timers: Con...
1135
  	if (!kc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1136
  		return -EINVAL;
5c4994102   Deepa Dinamani   posix-timers: Use...
1137
  	err = kc->clock_getres(which_clock, &ts);
9afc5eee6   Arnd Bergmann   y2038: globally r...
1138
  	if (!err && tp && put_old_timespec32(&ts, tp))
5c4994102   Deepa Dinamani   posix-timers: Use...
1139
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1140

5c4994102   Deepa Dinamani   posix-timers: Use...
1141
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
  }
5c4994102   Deepa Dinamani   posix-timers: Use...
1143

d822cdcce   Al Viro   posix-timers: Mov...
1144
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1145

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1146
  /*
97735f25d   Thomas Gleixner   [PATCH] hrtimer: ...
1147
1148
1149
   * nanosleep for monotonic and realtime clocks
   */
  static int common_nsleep(const clockid_t which_clock, int flags,
938e7cf2d   Thomas Gleixner   posix-timers: Mak...
1150
  			 const struct timespec64 *rqtp)
97735f25d   Thomas Gleixner   [PATCH] hrtimer: ...
1151
  {
ea2d1f7fc   Andrei Vagin   hrtimers: Prepare...
1152
1153
1154
  	ktime_t texp = timespec64_to_ktime(*rqtp);
  
  	return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ?
080344b98   Oleg Nesterov   hrtimer: fix *rmt...
1155
1156
  				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
  				 which_clock);
97735f25d   Thomas Gleixner   [PATCH] hrtimer: ...
1157
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158

1f9b37bfb   Andrei Vagin   posix-timers: Mak...
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
  static int common_nsleep_timens(const clockid_t which_clock, int flags,
  			 const struct timespec64 *rqtp)
  {
  	ktime_t texp = timespec64_to_ktime(*rqtp);
  
  	if (flags & TIMER_ABSTIME)
  		texp = timens_ktime_to_host(which_clock, texp);
  
  	return hrtimer_nanosleep(texp, flags & TIMER_ABSTIME ?
  				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
  				 which_clock);
  }
362e9c07c   Heiko Carstens   [CVE-2009-0029] S...
1171
  SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
01909974b   Deepa Dinamani   time: Change nano...
1172
1173
  		const struct __kernel_timespec __user *, rqtp,
  		struct __kernel_timespec __user *, rmtp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1175
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1176
  	struct timespec64 t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177

a5cd28801   Thomas Gleixner   posix-timers: Con...
1178
  	if (!kc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
  		return -EINVAL;
a5cd28801   Thomas Gleixner   posix-timers: Con...
1180
  	if (!kc->nsleep)
93cb8e20d   Helge Deller   parisc: Drop arch...
1181
  		return -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182

c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1183
  	if (get_timespec64(&t, rqtp))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
  		return -EFAULT;
c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1185
  	if (!timespec64_valid(&t))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
  		return -EINVAL;
99e6c0e6e   Al Viro   posix-timers: Sto...
1187
1188
  	if (flags & TIMER_ABSTIME)
  		rmtp = NULL;
edbeda463   Al Viro   time/posix-timers...
1189
  	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
99e6c0e6e   Al Viro   posix-timers: Sto...
1190
  	current->restart_block.nanosleep.rmtp = rmtp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1191

c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1192
  	return kc->nsleep(which_clock, flags, &t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193
  }
1711ef386   Toyo Abe   [PATCH] posix-tim...
1194

b5793b0d9   Deepa Dinamani   posix-timers: Mak...
1195
  #ifdef CONFIG_COMPAT_32BIT_TIME
8dabe7245   Arnd Bergmann   y2038: syscalls: ...
1196
1197
1198
  SYSCALL_DEFINE4(clock_nanosleep_time32, clockid_t, which_clock, int, flags,
  		struct old_timespec32 __user *, rqtp,
  		struct old_timespec32 __user *, rmtp)
1711ef386   Toyo Abe   [PATCH] posix-tim...
1199
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1200
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1201
  	struct timespec64 t;
59bd5bc24   Thomas Gleixner   posix-timers: Con...
1202

edbeda463   Al Viro   time/posix-timers...
1203
  	if (!kc)
59bd5bc24   Thomas Gleixner   posix-timers: Con...
1204
  		return -EINVAL;
edbeda463   Al Viro   time/posix-timers...
1205
  	if (!kc->nsleep)
93cb8e20d   Helge Deller   parisc: Drop arch...
1206
  		return -EOPNOTSUPP;
edbeda463   Al Viro   time/posix-timers...
1207

9afc5eee6   Arnd Bergmann   y2038: globally r...
1208
  	if (get_old_timespec32(&t, rqtp))
edbeda463   Al Viro   time/posix-timers...
1209
  		return -EFAULT;
1711ef386   Toyo Abe   [PATCH] posix-tim...
1210

c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1211
  	if (!timespec64_valid(&t))
edbeda463   Al Viro   time/posix-timers...
1212
1213
1214
1215
1216
  		return -EINVAL;
  	if (flags & TIMER_ABSTIME)
  		rmtp = NULL;
  	current->restart_block.nanosleep.type = rmtp ? TT_COMPAT : TT_NONE;
  	current->restart_block.nanosleep.compat_rmtp = rmtp;
c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1217
  	return kc->nsleep(which_clock, flags, &t);
1711ef386   Toyo Abe   [PATCH] posix-tim...
1218
  }
b5793b0d9   Deepa Dinamani   posix-timers: Mak...
1219

edbeda463   Al Viro   time/posix-timers...
1220
  #endif
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1221
1222
  
  static const struct k_clock clock_realtime = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1223
  	.clock_getres		= posix_get_hrtimer_res,
eaf80194d   Andrei Vagin   posix-clocks: Ren...
1224
  	.clock_get_timespec	= posix_get_realtime_timespec,
9c71a2e8a   Andrei Vagin   posix-clocks: Int...
1225
  	.clock_get_ktime	= posix_get_realtime_ktime,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1226
1227
1228
  	.clock_set		= posix_clock_realtime_set,
  	.clock_adj		= posix_clock_realtime_adj,
  	.nsleep			= common_nsleep,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1229
1230
1231
1232
1233
1234
1235
1236
  	.timer_create		= common_timer_create,
  	.timer_set		= common_timer_set,
  	.timer_get		= common_timer_get,
  	.timer_del		= common_timer_del,
  	.timer_rearm		= common_hrtimer_rearm,
  	.timer_forward		= common_hrtimer_forward,
  	.timer_remaining	= common_hrtimer_remaining,
  	.timer_try_to_cancel	= common_hrtimer_try_to_cancel,
ec8f954a4   Thomas Gleixner   posix-timers: Use...
1237
  	.timer_wait_running	= common_timer_wait_running,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1238
  	.timer_arm		= common_hrtimer_arm,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1239
1240
1241
  };
  
  static const struct k_clock clock_monotonic = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1242
  	.clock_getres		= posix_get_hrtimer_res,
eaf80194d   Andrei Vagin   posix-clocks: Ren...
1243
  	.clock_get_timespec	= posix_get_monotonic_timespec,
9c71a2e8a   Andrei Vagin   posix-clocks: Int...
1244
  	.clock_get_ktime	= posix_get_monotonic_ktime,
1f9b37bfb   Andrei Vagin   posix-timers: Mak...
1245
  	.nsleep			= common_nsleep_timens,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1246
1247
1248
1249
1250
1251
1252
1253
  	.timer_create		= common_timer_create,
  	.timer_set		= common_timer_set,
  	.timer_get		= common_timer_get,
  	.timer_del		= common_timer_del,
  	.timer_rearm		= common_hrtimer_rearm,
  	.timer_forward		= common_hrtimer_forward,
  	.timer_remaining	= common_hrtimer_remaining,
  	.timer_try_to_cancel	= common_hrtimer_try_to_cancel,
ec8f954a4   Thomas Gleixner   posix-timers: Use...
1254
  	.timer_wait_running	= common_timer_wait_running,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1255
  	.timer_arm		= common_hrtimer_arm,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1256
1257
1258
  };
  
  static const struct k_clock clock_monotonic_raw = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1259
  	.clock_getres		= posix_get_hrtimer_res,
819a95fe3   Andrei Vagin   posix-clocks: Ren...
1260
  	.clock_get_timespec	= posix_get_monotonic_raw,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1261
1262
1263
  };
  
  static const struct k_clock clock_realtime_coarse = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1264
  	.clock_getres		= posix_get_coarse_res,
819a95fe3   Andrei Vagin   posix-clocks: Ren...
1265
  	.clock_get_timespec	= posix_get_realtime_coarse,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1266
1267
1268
  };
  
  static const struct k_clock clock_monotonic_coarse = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1269
  	.clock_getres		= posix_get_coarse_res,
819a95fe3   Andrei Vagin   posix-clocks: Ren...
1270
  	.clock_get_timespec	= posix_get_monotonic_coarse,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1271
1272
1273
  };
  
  static const struct k_clock clock_tai = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1274
  	.clock_getres		= posix_get_hrtimer_res,
9c71a2e8a   Andrei Vagin   posix-clocks: Int...
1275
  	.clock_get_ktime	= posix_get_tai_ktime,
eaf80194d   Andrei Vagin   posix-clocks: Ren...
1276
  	.clock_get_timespec	= posix_get_tai_timespec,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1277
  	.nsleep			= common_nsleep,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1278
1279
1280
1281
1282
1283
1284
1285
  	.timer_create		= common_timer_create,
  	.timer_set		= common_timer_set,
  	.timer_get		= common_timer_get,
  	.timer_del		= common_timer_del,
  	.timer_rearm		= common_hrtimer_rearm,
  	.timer_forward		= common_hrtimer_forward,
  	.timer_remaining	= common_hrtimer_remaining,
  	.timer_try_to_cancel	= common_hrtimer_try_to_cancel,
ec8f954a4   Thomas Gleixner   posix-timers: Use...
1286
  	.timer_wait_running	= common_timer_wait_running,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1287
  	.timer_arm		= common_hrtimer_arm,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1288
  };
a3ed0e439   Thomas Gleixner   Revert: Unify CLO...
1289
  static const struct k_clock clock_boottime = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1290
  	.clock_getres		= posix_get_hrtimer_res,
9c71a2e8a   Andrei Vagin   posix-clocks: Int...
1291
  	.clock_get_ktime	= posix_get_boottime_ktime,
eaf80194d   Andrei Vagin   posix-clocks: Ren...
1292
  	.clock_get_timespec	= posix_get_boottime_timespec,
1f9b37bfb   Andrei Vagin   posix-timers: Mak...
1293
  	.nsleep			= common_nsleep_timens,
a3ed0e439   Thomas Gleixner   Revert: Unify CLO...
1294
1295
1296
1297
1298
1299
1300
1301
  	.timer_create		= common_timer_create,
  	.timer_set		= common_timer_set,
  	.timer_get		= common_timer_get,
  	.timer_del		= common_timer_del,
  	.timer_rearm		= common_hrtimer_rearm,
  	.timer_forward		= common_hrtimer_forward,
  	.timer_remaining	= common_hrtimer_remaining,
  	.timer_try_to_cancel	= common_hrtimer_try_to_cancel,
ec8f954a4   Thomas Gleixner   posix-timers: Use...
1302
  	.timer_wait_running	= common_timer_wait_running,
a3ed0e439   Thomas Gleixner   Revert: Unify CLO...
1303
  	.timer_arm		= common_hrtimer_arm,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
  };
  
  static const struct k_clock * const posix_clocks[] = {
  	[CLOCK_REALTIME]		= &clock_realtime,
  	[CLOCK_MONOTONIC]		= &clock_monotonic,
  	[CLOCK_PROCESS_CPUTIME_ID]	= &clock_process,
  	[CLOCK_THREAD_CPUTIME_ID]	= &clock_thread,
  	[CLOCK_MONOTONIC_RAW]		= &clock_monotonic_raw,
  	[CLOCK_REALTIME_COARSE]		= &clock_realtime_coarse,
  	[CLOCK_MONOTONIC_COARSE]	= &clock_monotonic_coarse,
a3ed0e439   Thomas Gleixner   Revert: Unify CLO...
1314
  	[CLOCK_BOOTTIME]		= &clock_boottime,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1315
1316
1317
1318
1319
1320
1321
  	[CLOCK_REALTIME_ALARM]		= &alarm_clock,
  	[CLOCK_BOOTTIME_ALARM]		= &alarm_clock,
  	[CLOCK_TAI]			= &clock_tai,
  };
  
  static const struct k_clock *clockid_to_kclock(const clockid_t id)
  {
19b558db1   Thomas Gleixner   posix-timers: Pro...
1322
1323
1324
  	clockid_t idx = id;
  
  	if (id < 0) {
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1325
1326
  		return (id & CLOCKFD_MASK) == CLOCKFD ?
  			&clock_posix_dynamic : &clock_posix_cpu;
19b558db1   Thomas Gleixner   posix-timers: Pro...
1327
  	}
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1328

19b558db1   Thomas Gleixner   posix-timers: Pro...
1329
  	if (id >= ARRAY_SIZE(posix_clocks))
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1330
  		return NULL;
19b558db1   Thomas Gleixner   posix-timers: Pro...
1331
1332
  
  	return posix_clocks[array_index_nospec(idx, ARRAY_SIZE(posix_clocks))];
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1333
  }