Blame view

kernel/time/posix-timers.c 35.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
f30c22695   Uwe Zeisberger   fix file specific...
2
   * linux/kernel/posix-timers.c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   *
   *
   * 2002-10-15  Posix Clocks & timers
   *                           by George Anzinger george@mvista.com
   *
   *			     Copyright (C) 2002 2003 by MontaVista Software.
   *
   * 2004-06-01  Fix CLOCK_REALTIME clock/timer TIMER_ABSTIME bug.
   *			     Copyright (C) 2004 Boris Hu
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or (at
   * your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
  
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   *
   * MontaVista Software | 1237 East Arques Avenue | Sunnyvale | CA 94085 | USA
   */
  
  /* These are all the functions necessary to implement
   * POSIX clocks & timers
   */
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
  #include <linux/interrupt.h>
  #include <linux/slab.h>
  #include <linux/time.h>
97d1f15b7   Arjan van de Ven   [PATCH] sem2mutex...
37
  #include <linux/mutex.h>
61855b6b0   Ingo Molnar   sched/headers: Pr...
38
  #include <linux/sched/task.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39

7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
40
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
  #include <linux/list.h>
  #include <linux/init.h>
  #include <linux/compiler.h>
5ed67f05f   Pavel Emelyanov   posix timers: All...
44
  #include <linux/hash.h>
0606f422b   Richard Cochran   posix clocks: Int...
45
  #include <linux/posix-clock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
49
  #include <linux/posix-timers.h>
  #include <linux/syscalls.h>
  #include <linux/wait.h>
  #include <linux/workqueue.h>
9984de1a5   Paul Gortmaker   kernel: Map most ...
50
  #include <linux/export.h>
5ed67f05f   Pavel Emelyanov   posix timers: All...
51
  #include <linux/hashtable.h>
edbeda463   Al Viro   time/posix-timers...
52
  #include <linux/compat.h>
f7fbe38cc   Thomas Gleixner   posix-timers: Pro...
53
  #include <linux/nospec.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54

8b094cd03   Thomas Gleixner   time: Consolidate...
55
  #include "timekeeping.h"
bab0aae9d   Thomas Gleixner   posix-timers: Mov...
56
  #include "posix-timers.h"
8b094cd03   Thomas Gleixner   time: Consolidate...
57

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  /*
5ed67f05f   Pavel Emelyanov   posix timers: All...
59
60
61
62
63
64
   * 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
65
66
67
68
69
   */
  
  /*
   * Lets keep our timers in a slab cache :-)
   */
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
70
  static struct kmem_cache *posix_timers_cache;
5ed67f05f   Pavel Emelyanov   posix timers: All...
71
72
73
  
  static DEFINE_HASHTABLE(posix_timers_hashtable, 9);
  static DEFINE_SPINLOCK(hash_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74

6631fa12c   Thomas Gleixner   posix-timers: Avo...
75
76
  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...
77
  static const struct k_clock clock_realtime, clock_monotonic;
6631fa12c   Thomas Gleixner   posix-timers: Avo...
78

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
83
84
85
86
   * 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...
87
88
89
90
91
92
93
94
  /*
   * parisc wants ENOTSUP instead of EOPNOTSUPP
   */
  #ifndef ENOTSUP
  # define ENANOSLEEP_NOTSUP EOPNOTSUPP
  #else
  # define ENANOSLEEP_NOTSUP ENOTSUP
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
98
99
100
101
102
103
104
105
106
107
  
  /*
   * 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...
108
   *	    clocks.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
115
116
117
   *
   * 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...
118
119
   * FUNCTIONS: The CLOCKs structure defines possible functions to
   *	    handle various clock functions.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
   *
0061748dd   Richard Cochran   posix-timer: Upda...
121
122
123
124
   *	    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
125
126
127
128
129
130
131
132
   *
   * 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...
133
134
135
136
137
138
139
  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
140

5ed67f05f   Pavel Emelyanov   posix timers: All...
141
142
143
144
145
146
147
148
149
  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...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  	struct k_itimer *timer;
  
  	hlist_for_each_entry_rcu(timer, head, t_hash) {
  		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
190
191
192
193
  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...
194
  /* Get clock_realtime */
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
195
  static int posix_clock_realtime_get(clockid_t which_clock, struct timespec64 *tp)
422857776   Thomas Gleixner   posix-timers: Con...
196
  {
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
197
  	ktime_get_real_ts64(tp);
422857776   Thomas Gleixner   posix-timers: Con...
198
199
  	return 0;
  }
26f9a4796   Thomas Gleixner   posix-timers: Con...
200
201
  /* Set clock_realtime */
  static int posix_clock_realtime_set(const clockid_t which_clock,
0fe6afe38   Deepa Dinamani   time: Change k_cl...
202
  				    const struct timespec64 *tp)
26f9a4796   Thomas Gleixner   posix-timers: Con...
203
  {
0fe6afe38   Deepa Dinamani   time: Change k_cl...
204
  	return do_sys_settimeofday64(tp, NULL);
26f9a4796   Thomas Gleixner   posix-timers: Con...
205
  }
f1f1d5ebd   Richard Cochran   posix-timers: Int...
206
207
208
209
210
  static int posix_clock_realtime_adj(const clockid_t which_clock,
  				    struct timex *t)
  {
  	return do_adjtimex(t);
  }
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
211
212
213
  /*
   * Get monotonic time for posix timers
   */
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
214
  static int posix_ktime_get_ts(clockid_t which_clock, struct timespec64 *tp)
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
215
  {
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
216
  	ktime_get_ts64(tp);
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
217
218
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
  
  /*
7fdd7f890   John Stultz   timers: Export CL...
221
   * Get monotonic-raw time for posix timers
2d42244ae   John Stultz   clocksource: intr...
222
   */
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
223
  static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec64 *tp)
2d42244ae   John Stultz   clocksource: intr...
224
  {
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
225
  	getrawmonotonic64(tp);
2d42244ae   John Stultz   clocksource: intr...
226
227
  	return 0;
  }
da15cfdae   John Stultz   time: Introduce C...
228

3c9c12f4b   Deepa Dinamani   time: Change k_cl...
229
  static int posix_get_realtime_coarse(clockid_t which_clock, struct timespec64 *tp)
da15cfdae   John Stultz   time: Introduce C...
230
  {
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
231
  	*tp = current_kernel_time64();
da15cfdae   John Stultz   time: Introduce C...
232
233
234
235
  	return 0;
  }
  
  static int posix_get_monotonic_coarse(clockid_t which_clock,
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
236
  						struct timespec64 *tp)
da15cfdae   John Stultz   time: Introduce C...
237
  {
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
238
  	*tp = get_monotonic_coarse64();
da15cfdae   John Stultz   time: Introduce C...
239
240
  	return 0;
  }
d2e3e0ca5   Deepa Dinamani   time: Change k_cl...
241
  static int posix_get_coarse_res(const clockid_t which_clock, struct timespec64 *tp)
da15cfdae   John Stultz   time: Introduce C...
242
  {
d2e3e0ca5   Deepa Dinamani   time: Change k_cl...
243
  	*tp = ktime_to_timespec64(KTIME_LOW_RES);
da15cfdae   John Stultz   time: Introduce C...
244
245
  	return 0;
  }
7fdd7f890   John Stultz   timers: Export CL...
246

3c9c12f4b   Deepa Dinamani   time: Change k_cl...
247
  static int posix_get_boottime(const clockid_t which_clock, struct timespec64 *tp)
7fdd7f890   John Stultz   timers: Export CL...
248
  {
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
249
  	get_monotonic_boottime64(tp);
7fdd7f890   John Stultz   timers: Export CL...
250
251
  	return 0;
  }
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
252
  static int posix_get_tai(clockid_t which_clock, struct timespec64 *tp)
1ff3c9677   John Stultz   timekeeping: Add ...
253
  {
3c9c12f4b   Deepa Dinamani   time: Change k_cl...
254
  	timekeeping_clocktai64(tp);
1ff3c9677   John Stultz   timekeeping: Add ...
255
256
  	return 0;
  }
7fdd7f890   John Stultz   timers: Export CL...
257

d2e3e0ca5   Deepa Dinamani   time: Change k_cl...
258
  static int posix_get_hrtimer_res(clockid_t which_clock, struct timespec64 *tp)
056a3cacb   Thomas Gleixner   hrtimer: Get rid ...
259
260
261
262
263
  {
  	tp->tv_sec = 0;
  	tp->tv_nsec = hrtimer_resolution;
  	return 0;
  }
2d42244ae   John Stultz   clocksource: intr...
264
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
   * Initialize everything, well, just everything in Posix clocks/timers ;)
   */
  static __init int init_posix_timers(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  	posix_timers_cache = kmem_cache_create("posix_timers_cache",
040b5c6f9   Alexey Dobriyan   SLAB_PANIC more (...
270
271
  					sizeof (struct k_itimer), 0, SLAB_PANIC,
  					NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  __initcall(init_posix_timers);
3e3f075f7   Thomas Gleixner   posix-timers: San...
275
276
277
278
279
280
281
282
283
284
  /*
   * 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...
285
  static void common_hrtimer_rearm(struct k_itimer *timr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
  {
44f214755   Roman Zippel   [PATCH] hrtimers:...
287
  	struct hrtimer *timer = &timr->it.real.timer;
3e3f075f7   Thomas Gleixner   posix-timers: San...
288
289
  	timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(),
  					    timr->it_interval);
44f214755   Roman Zippel   [PATCH] hrtimers:...
290
  	hrtimer_restart(timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
294
295
296
297
298
299
300
  }
  
  /*
   * 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...
301
   * To protect against the timer going away while the interrupt is queued,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
   * we require that the it_requeue_pending flag be set.
   */
96fe3b072   Thomas Gleixner   posix-timers: Ren...
304
  void posixtimer_rearm(struct siginfo *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
307
308
309
  {
  	struct k_itimer *timr;
  	unsigned long flags;
  
  	timr = lock_timer(info->si_tid, &flags);
af888d677   Thomas Gleixner   posix-timers: Uni...
310
311
  	if (!timr)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312

2f8f9e280   Thomas Gleixner   posix-timers: Fix...
313
  	if (timr->it_interval && timr->it_requeue_pending == info->si_sys_private) {
f37fb0aa4   Thomas Gleixner   posix-timers: Use...
314
  		timr->kclock->timer_rearm(timr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315

21e55c1f8   Thomas Gleixner   posix-timers: Add...
316
  		timr->it_active = 1;
af888d677   Thomas Gleixner   posix-timers: Uni...
317
  		timr->it_overrun_last = timr->it_overrun;
3e3f075f7   Thomas Gleixner   posix-timers: San...
318
  		timr->it_overrun = -1LL;
af888d677   Thomas Gleixner   posix-timers: Uni...
319
  		++timr->it_requeue_pending;
3e3f075f7   Thomas Gleixner   posix-timers: San...
320
  		info->si_overrun = timer_overrun_to_int(timr, info->si_overrun);
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
321
  	}
af888d677   Thomas Gleixner   posix-timers: Uni...
322
  	unlock_timer(timr, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
  }
ba661292a   Oleg Nesterov   posix-timers: fix...
324
  int posix_timer_event(struct k_itimer *timr, int si_private)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  {
27af4245b   Oleg Nesterov   posix-timers: use...
326
327
  	struct task_struct *task;
  	int shared, ret = -1;
ba661292a   Oleg Nesterov   posix-timers: fix...
328
329
  	/*
  	 * FIXME: if ->sigq is queued we can race with
96fe3b072   Thomas Gleixner   posix-timers: Ren...
330
  	 * dequeue_signal()->posixtimer_rearm().
ba661292a   Oleg Nesterov   posix-timers: fix...
331
332
  	 *
  	 * If dequeue_signal() sees the "right" value of
96fe3b072   Thomas Gleixner   posix-timers: Ren...
333
  	 * si_sys_private it calls posixtimer_rearm().
ba661292a   Oleg Nesterov   posix-timers: fix...
334
  	 * We re-queue ->sigq and drop ->it_lock().
96fe3b072   Thomas Gleixner   posix-timers: Ren...
335
  	 * posixtimer_rearm() locks the timer
ba661292a   Oleg Nesterov   posix-timers: fix...
336
337
338
  	 * and re-schedules it while ->sigq is pending.
  	 * Not really bad, but not that we want.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  	timr->sigq->info.si_sys_private = si_private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340

27af4245b   Oleg Nesterov   posix-timers: use...
341
342
343
344
345
346
347
  	rcu_read_lock();
  	task = pid_task(timr->it_pid, PIDTYPE_PID);
  	if (task) {
  		shared = !(timr->it_sigev_notify & SIGEV_THREAD_ID);
  		ret = send_sigqueue(timr->sigq, task, shared);
  	}
  	rcu_read_unlock();
4aa736117   Oleg Nesterov   posix-timers: don...
348
349
  	/* If we failed to send the signal the timer stops. */
  	return ret > 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
357
358
  
  /*
   * 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:...
359
  static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  {
05cfb614d   Roman Zippel   [PATCH] hrtimers:...
361
  	struct k_itimer *timr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
  	unsigned long flags;
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
363
  	int si_private = 0;
c9cb2e3d7   Thomas Gleixner   [PATCH] hrtimers:...
364
  	enum hrtimer_restart ret = HRTIMER_NORESTART;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365

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

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

becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
373
374
375
376
377
378
  	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...
379
  		if (timr->it_interval != 0) {
58229a189   Thomas Gleixner   posix-timers: Pre...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  			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...
406
  				ktime_t kj = NSEC_PER_SEC / HZ;
58229a189   Thomas Gleixner   posix-timers: Pre...
407

80105cd0e   Thomas Gleixner   posix-timers: Mov...
408
  				if (timr->it_interval < kj)
58229a189   Thomas Gleixner   posix-timers: Pre...
409
410
411
  					now = ktime_add(now, kj);
  			}
  #endif
3e3f075f7   Thomas Gleixner   posix-timers: San...
412
413
  			timr->it_overrun += hrtimer_forward(timer, now,
  							    timr->it_interval);
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
414
  			ret = HRTIMER_RESTART;
a0a0c28c1   Roman Zippel   [PATCH] posix-tim...
415
  			++timr->it_requeue_pending;
21e55c1f8   Thomas Gleixner   posix-timers: Add...
416
  			timr->it_active = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419

becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
420
421
422
  	unlock_timer(timr, flags);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423

27af4245b   Oleg Nesterov   posix-timers: use...
424
  static struct pid *good_sigevent(sigevent_t * event)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
  {
  	struct task_struct *rtn = current->group_leader;
3df23f7ce   Thomas Gleixner   posix-timer: Prop...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
  	switch (event->sigev_notify) {
  	case SIGEV_SIGNAL | SIGEV_THREAD_ID:
  		rtn = find_task_by_vpid(event->sigev_notify_thread_id);
  		if (!rtn || !same_thread_group(rtn, current))
  			return NULL;
  		/* FALLTHRU */
  	case SIGEV_SIGNAL:
  	case SIGEV_THREAD:
  		if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX)
  			return NULL;
  		/* FALLTHRU */
  	case SIGEV_NONE:
  		return task_pid(rtn);
  	default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  		return NULL;
3df23f7ce   Thomas Gleixner   posix-timer: Prop...
442
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
  static struct k_itimer * alloc_posix_timer(void)
  {
  	struct k_itimer *tmr;
c37622296   Robert P. J. Day   [PATCH] Transform...
447
  	tmr = kmem_cache_zalloc(posix_timers_cache, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
  	if (!tmr)
  		return tmr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
  	if (unlikely(!(tmr->sigq = sigqueue_alloc()))) {
  		kmem_cache_free(posix_timers_cache, tmr);
aa94fbd5c   Dan Carpenter   fix error-path NU...
452
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
  	}
ba661292a   Oleg Nesterov   posix-timers: fix...
454
  	memset(&tmr->sigq->info, 0, sizeof(siginfo_t));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
  	return tmr;
  }
8af088710   Eric Dumazet   posix-timers: RCU...
457
458
459
460
461
462
  static void k_itimer_rcu_free(struct rcu_head *head)
  {
  	struct k_itimer *tmr = container_of(head, struct k_itimer, it.rcu);
  
  	kmem_cache_free(posix_timers_cache, tmr);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
466
467
468
  #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...
469
470
471
  		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
472
  	}
899921025   Oleg Nesterov   posix-timers: che...
473
  	put_pid(tmr->it_pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  	sigqueue_free(tmr->sigq);
8af088710   Eric Dumazet   posix-timers: RCU...
475
  	call_rcu(&tmr->it.rcu, k_itimer_rcu_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
  }
838394fbf   Thomas Gleixner   posix-timers: Con...
477
478
479
480
481
  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
482
  /* Create a POSIX.1b interval timer. */
2482097c6   Al Viro   posix-timers: Mov...
483
484
  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
485
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
486
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
2cd499e38   Oleg Nesterov   posix-timers: sys...
487
  	struct k_itimer *new_timer;
ef864c958   Oleg Nesterov   posix-timers: sys...
488
  	int error, new_timer_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
489
  	int it_id_set = IT_ID_NOT_SET;
838394fbf   Thomas Gleixner   posix-timers: Con...
490
  	if (!kc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
  		return -EINVAL;
838394fbf   Thomas Gleixner   posix-timers: Con...
492
493
  	if (!kc->timer_create)
  		return -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
496
497
498
499
  
  	new_timer = alloc_posix_timer();
  	if (unlikely(!new_timer))
  		return -EAGAIN;
  
  	spin_lock_init(&new_timer->it_lock);
5ed67f05f   Pavel Emelyanov   posix timers: All...
500
501
502
  	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
503
504
505
506
507
508
  		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...
509
  	new_timer->kclock = kc;
3e3f075f7   Thomas Gleixner   posix-timers: San...
510
  	new_timer->it_overrun = -1LL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511

2482097c6   Al Viro   posix-timers: Mov...
512
  	if (event) {
36b2f0460   Oleg Nesterov   posix-timers: sys...
513
  		rcu_read_lock();
2482097c6   Al Viro   posix-timers: Mov...
514
  		new_timer->it_pid = get_pid(good_sigevent(event));
36b2f0460   Oleg Nesterov   posix-timers: sys...
515
  		rcu_read_unlock();
899921025   Oleg Nesterov   posix-timers: che...
516
  		if (!new_timer->it_pid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
519
  			error = -EINVAL;
  			goto out;
  		}
2482097c6   Al Viro   posix-timers: Mov...
520
521
522
  		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
523
  	} else {
2482097c6   Al Viro   posix-timers: Mov...
524
525
526
527
  		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...
528
  		new_timer->it_pid = get_pid(task_tgid(current));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
  	}
717835d94   Oleg Nesterov   posix-timers: mov...
530
  	new_timer->sigq->info.si_tid   = new_timer->it_id;
5a9fa7307   Oleg Nesterov   posix-timers: kil...
531
  	new_timer->sigq->info.si_code  = SI_TIMER;
717835d94   Oleg Nesterov   posix-timers: mov...
532

2b08de007   Andrey Vagin   posix_timer: Move...
533
534
535
536
537
  	if (copy_to_user(created_timer_id,
  			 &new_timer_id, sizeof (new_timer_id))) {
  		error = -EFAULT;
  		goto out;
  	}
838394fbf   Thomas Gleixner   posix-timers: Con...
538
  	error = kc->timer_create(new_timer);
45e0fffc8   Andrey Vagin   posix_timer: Fix ...
539
540
  	if (error)
  		goto out;
36b2f0460   Oleg Nesterov   posix-timers: sys...
541
  	spin_lock_irq(&current->sighand->siglock);
27af4245b   Oleg Nesterov   posix-timers: use...
542
  	new_timer->it_signal = current->signal;
36b2f0460   Oleg Nesterov   posix-timers: sys...
543
544
  	list_add(&new_timer->list, &current->signal->posix_timers);
  	spin_unlock_irq(&current->sighand->siglock);
ef864c958   Oleg Nesterov   posix-timers: sys...
545
546
  
  	return 0;
838394fbf   Thomas Gleixner   posix-timers: Con...
547
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
550
551
552
  	 * 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
553
  out:
ef864c958   Oleg Nesterov   posix-timers: sys...
554
  	release_posix_timer(new_timer, it_id_set);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
556
  	return error;
  }
2482097c6   Al Viro   posix-timers: Mov...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
  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
586
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
588
589
590
591
592
   * 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...
593
  static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
  {
  	struct k_itimer *timr;
8af088710   Eric Dumazet   posix-timers: RCU...
596

e182bb38d   Tejun Heo   posix-timer: Don'...
597
598
599
600
601
602
  	/*
  	 * 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...
603
  	rcu_read_lock();
5ed67f05f   Pavel Emelyanov   posix timers: All...
604
  	timr = posix_timer_by_id(timer_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  	if (timr) {
8af088710   Eric Dumazet   posix-timers: RCU...
606
  		spin_lock_irqsave(&timr->it_lock, *flags);
899921025   Oleg Nesterov   posix-timers: che...
607
  		if (timr->it_signal == current->signal) {
8af088710   Eric Dumazet   posix-timers: RCU...
608
  			rcu_read_unlock();
31d928456   Oleg Nesterov   posix-timers: loc...
609
610
  			return timr;
  		}
8af088710   Eric Dumazet   posix-timers: RCU...
611
  		spin_unlock_irqrestore(&timr->it_lock, *flags);
31d928456   Oleg Nesterov   posix-timers: loc...
612
  	}
8af088710   Eric Dumazet   posix-timers: RCU...
613
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614

31d928456   Oleg Nesterov   posix-timers: loc...
615
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
  }
91d57bae0   Thomas Gleixner   posix-timers: Mak...
617
618
619
620
621
622
  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);
  }
a05bd4ba6   Thomas Gleixner   posix-timers: Mak...
623
  static s64 common_hrtimer_forward(struct k_itimer *timr, ktime_t now)
91d57bae0   Thomas Gleixner   posix-timers: Mak...
624
625
  {
  	struct hrtimer *timer = &timr->it.real.timer;
a05bd4ba6   Thomas Gleixner   posix-timers: Mak...
626
  	return hrtimer_forward(timer, now, timr->it_interval);
91d57bae0   Thomas Gleixner   posix-timers: Mak...
627
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
  /*
   * 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...
644
  void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
  {
91d57bae0   Thomas Gleixner   posix-timers: Mak...
646
  	const struct k_clock *kc = timr->kclock;
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
647
  	ktime_t now, remaining, iv;
91d57bae0   Thomas Gleixner   posix-timers: Mak...
648
649
  	struct timespec64 ts64;
  	bool sig_none;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650

3df23f7ce   Thomas Gleixner   posix-timer: Prop...
651
  	sig_none = timr->it_sigev_notify == SIGEV_NONE;
80105cd0e   Thomas Gleixner   posix-timers: Mov...
652
  	iv = timr->it_interval;
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
653

becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
654
  	/* interval timer ? */
91d57bae0   Thomas Gleixner   posix-timers: Mak...
655
  	if (iv) {
5f252b325   Deepa Dinamani   time: Change k_cl...
656
  		cur_setting->it_interval = ktime_to_timespec64(iv);
91d57bae0   Thomas Gleixner   posix-timers: Mak...
657
658
659
660
661
662
663
664
  	} else if (!timr->it_active) {
  		/*
  		 * SIGEV_NONE oneshot timers are never queued. Check them
  		 * below.
  		 */
  		if (!sig_none)
  			return;
  	}
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
665

91d57bae0   Thomas Gleixner   posix-timers: Mak...
666
667
668
669
670
671
  	/*
  	 * The timespec64 based conversion is suboptimal, but it's not
  	 * worth to implement yet another callback.
  	 */
  	kc->clock_get(timr->it_clock, &ts64);
  	now = timespec64_to_ktime(ts64);
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
672

becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
673
  	/*
91d57bae0   Thomas Gleixner   posix-timers: Mak...
674
675
  	 * 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: ...
676
  	 */
91d57bae0   Thomas Gleixner   posix-timers: Mak...
677
  	if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none))
3e3f075f7   Thomas Gleixner   posix-timers: San...
678
  		timr->it_overrun += kc->timer_forward(timr, now);
3b98a5328   Roman Zippel   [PATCH] hrtimers:...
679

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

b0dc12426   Al Viro   posix-timers: Tak...
716
717
718
719
  /* Get the time remaining on a POSIX.1b interval timer. */
  SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
  		struct itimerspec __user *, setting)
  {
725816e8a   Deepa Dinamani   posix_clocks: Use...
720
  	struct itimerspec64 cur_setting;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721

725816e8a   Deepa Dinamani   posix_clocks: Use...
722
  	int ret = do_timer_gettime(timer_id, &cur_setting);
b0dc12426   Al Viro   posix-timers: Tak...
723
  	if (!ret) {
725816e8a   Deepa Dinamani   posix_clocks: Use...
724
  		if (put_itimerspec64(&cur_setting, setting))
b0dc12426   Al Viro   posix-timers: Tak...
725
726
  			ret = -EFAULT;
  	}
a7319fa25   Thomas Gleixner   posix-timers: Con...
727
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
  }
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
729

b0dc12426   Al Viro   posix-timers: Tak...
730
731
732
733
  #ifdef CONFIG_COMPAT
  COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
  		       struct compat_itimerspec __user *, setting)
  {
725816e8a   Deepa Dinamani   posix_clocks: Use...
734
  	struct itimerspec64 cur_setting;
b0dc12426   Al Viro   posix-timers: Tak...
735

725816e8a   Deepa Dinamani   posix_clocks: Use...
736
  	int ret = do_timer_gettime(timer_id, &cur_setting);
b0dc12426   Al Viro   posix-timers: Tak...
737
  	if (!ret) {
725816e8a   Deepa Dinamani   posix_clocks: Use...
738
  		if (put_compat_itimerspec64(&cur_setting, setting))
b0dc12426   Al Viro   posix-timers: Tak...
739
740
741
742
743
  			ret = -EFAULT;
  	}
  	return ret;
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
747
748
749
  /*
   * 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...
750
   * the call back to posixtimer_rearm().  So all we need to do is
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
752
   * to pick up the frozen overrun.
   */
362e9c07c   Heiko Carstens   [CVE-2009-0029] S...
753
  SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
755
756
  {
  	struct k_itimer *timr;
  	int overrun;
5ba253313   Al Viro   more low-hanging ...
757
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758
759
760
761
  
  	timr = lock_timer(timer_id, &flags);
  	if (!timr)
  		return -EINVAL;
3e3f075f7   Thomas Gleixner   posix-timers: San...
762
  	overrun = timer_overrun_to_int(timr, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
764
765
766
  	unlock_timer(timr, flags);
  
  	return overrun;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767

eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
768
769
770
771
772
773
774
  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...
775
776
777
778
779
780
781
782
783
784
785
  	/*
  	 * 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
  	 * functions which use timr->kclock->clock_get() work.
  	 *
  	 * 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...
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
  	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);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
  /* Set a POSIX.1b interval timer. */
f2c45807d   Thomas Gleixner   alarmtimer: Switc...
802
803
804
  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
805
  {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
806
807
808
  	const struct k_clock *kc = timr->kclock;
  	bool sigev_none;
  	ktime_t expires;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
810
811
  
  	if (old_setting)
  		common_timer_get(timr, old_setting);
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
812
  	/* Prevent rearming by clearing the interval */
80105cd0e   Thomas Gleixner   posix-timers: Mov...
813
  	timr->it_interval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
  	/*
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
815
816
  	 * 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
817
  	 */
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
818
  	if (kc->timer_try_to_cancel(timr) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
  		return TIMER_RETRY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820

21e55c1f8   Thomas Gleixner   posix-timers: Add...
821
822
  	timr->it_active = 0;
  	timr->it_requeue_pending = (timr->it_requeue_pending + 2) &
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
824
  		~REQUEUE_PENDING;
  	timr->it_overrun_last = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825

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

80105cd0e   Thomas Gleixner   posix-timers: Mov...
830
  	timr->it_interval = timespec64_to_ktime(new_setting->it_interval);
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
831
  	expires = timespec64_to_ktime(new_setting->it_value);
3df23f7ce   Thomas Gleixner   posix-timer: Prop...
832
  	sigev_none = timr->it_sigev_notify == SIGEV_NONE;
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
833

eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
834
835
  	kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none);
  	timr->it_active = !sigev_none;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836
837
  	return 0;
  }
1acbe7708   Al Viro   posix-timers: Tak...
838
839
840
  static int do_timer_settime(timer_t timer_id, int flags,
  			    struct itimerspec64 *new_spec64,
  			    struct itimerspec64 *old_spec64)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
  {
1acbe7708   Al Viro   posix-timers: Tak...
842
  	const struct k_clock *kc;
5f252b325   Deepa Dinamani   time: Change k_cl...
843
  	struct k_itimer *timr;
5ba253313   Al Viro   more low-hanging ...
844
  	unsigned long flag;
5f252b325   Deepa Dinamani   time: Change k_cl...
845
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846

1acbe7708   Al Viro   posix-timers: Tak...
847
848
  	if (!timespec64_valid(&new_spec64->it_interval) ||
  	    !timespec64_valid(&new_spec64->it_value))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
  		return -EINVAL;
1acbe7708   Al Viro   posix-timers: Tak...
850
851
  	if (old_spec64)
  		memset(old_spec64, 0, sizeof(*old_spec64));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
853
854
855
  retry:
  	timr = lock_timer(timer_id, &flag);
  	if (!timr)
  		return -EINVAL;
d97bb75dd   Thomas Gleixner   posix-timers: Sto...
856
  	kc = timr->kclock;
27722df16   Thomas Gleixner   posix-timers: Con...
857
858
859
  	if (WARN_ON_ONCE(!kc || !kc->timer_set))
  		error = -EINVAL;
  	else
1acbe7708   Al Viro   posix-timers: Tak...
860
  		error = kc->timer_set(timr, flags, new_spec64, old_spec64);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
862
863
  
  	unlock_timer(timr, flag);
  	if (error == TIMER_RETRY) {
1acbe7708   Al Viro   posix-timers: Tak...
864
  		old_spec64 = NULL;	// We already got the old time...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865
866
  		goto retry;
  	}
1acbe7708   Al Viro   posix-timers: Tak...
867
868
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869

1acbe7708   Al Viro   posix-timers: Tak...
870
871
872
873
874
  /* Set a POSIX.1b interval timer */
  SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
  		const struct itimerspec __user *, new_setting,
  		struct itimerspec __user *, old_setting)
  {
725816e8a   Deepa Dinamani   posix_clocks: Use...
875
876
  	struct itimerspec64 new_spec, old_spec;
  	struct itimerspec64 *rtn = old_setting ? &old_spec : NULL;
1acbe7708   Al Viro   posix-timers: Tak...
877
878
879
880
  	int error = 0;
  
  	if (!new_setting)
  		return -EINVAL;
725816e8a   Deepa Dinamani   posix_clocks: Use...
881
  	if (get_itimerspec64(&new_spec, new_setting))
1acbe7708   Al Viro   posix-timers: Tak...
882
  		return -EFAULT;
1acbe7708   Al Viro   posix-timers: Tak...
883

725816e8a   Deepa Dinamani   posix_clocks: Use...
884
  	error = do_timer_settime(timer_id, flags, &new_spec, rtn);
1acbe7708   Al Viro   posix-timers: Tak...
885
  	if (!error && old_setting) {
725816e8a   Deepa Dinamani   posix_clocks: Use...
886
  		if (put_itimerspec64(&old_spec, old_setting))
1acbe7708   Al Viro   posix-timers: Tak...
887
888
889
890
891
892
893
894
895
896
  			error = -EFAULT;
  	}
  	return error;
  }
  
  #ifdef CONFIG_COMPAT
  COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
  		       struct compat_itimerspec __user *, new,
  		       struct compat_itimerspec __user *, old)
  {
725816e8a   Deepa Dinamani   posix_clocks: Use...
897
898
  	struct itimerspec64 new_spec, old_spec;
  	struct itimerspec64 *rtn = old ? &old_spec : NULL;
1acbe7708   Al Viro   posix-timers: Tak...
899
900
901
902
  	int error = 0;
  
  	if (!new)
  		return -EINVAL;
725816e8a   Deepa Dinamani   posix_clocks: Use...
903
  	if (get_compat_itimerspec64(&new_spec, new))
1acbe7708   Al Viro   posix-timers: Tak...
904
  		return -EFAULT;
725816e8a   Deepa Dinamani   posix_clocks: Use...
905
  	error = do_timer_settime(timer_id, flags, &new_spec, rtn);
1acbe7708   Al Viro   posix-timers: Tak...
906
  	if (!error && old) {
725816e8a   Deepa Dinamani   posix_clocks: Use...
907
  		if (put_compat_itimerspec64(&old_spec, old))
1acbe7708   Al Viro   posix-timers: Tak...
908
909
  			error = -EFAULT;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
910
911
  	return error;
  }
1acbe7708   Al Viro   posix-timers: Tak...
912
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913

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

eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
918
919
  	timer->it_interval = 0;
  	if (kc->timer_try_to_cancel(timer) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
  		return TIMER_RETRY;
21e55c1f8   Thomas Gleixner   posix-timers: Add...
921
  	timer->it_active = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922
923
924
925
926
  	return 0;
  }
  
  static inline int timer_delete_hook(struct k_itimer *timer)
  {
d97bb75dd   Thomas Gleixner   posix-timers: Sto...
927
  	const struct k_clock *kc = timer->kclock;
6761c6702   Thomas Gleixner   posix-timers: Con...
928
929
930
931
  
  	if (WARN_ON_ONCE(!kc || !kc->timer_del))
  		return -EINVAL;
  	return kc->timer_del(timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
932
933
934
  }
  
  /* Delete a POSIX.1b interval timer. */
362e9c07c   Heiko Carstens   [CVE-2009-0029] S...
935
  SYSCALL_DEFINE1(timer_delete, timer_t, timer_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
937
  {
  	struct k_itimer *timer;
5ba253313   Al Viro   more low-hanging ...
938
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
  retry_delete:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
942
943
  	timer = lock_timer(timer_id, &flags);
  	if (!timer)
  		return -EINVAL;
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
944
  	if (timer_delete_hook(timer) == TIMER_RETRY) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
945
946
947
  		unlock_timer(timer, flags);
  		goto retry_delete;
  	}
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
948

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949
950
951
952
953
954
955
  	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...
956
  	timer->it_signal = NULL;
4b7a13042   Oleg Nesterov   posix timers: tim...
957

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
959
960
961
  	unlock_timer(timer, flags);
  	release_posix_timer(timer, IT_ID_SET);
  	return 0;
  }
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
962

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
964
965
  /*
   * return timer owned by the process, used by exit_itimers
   */
858119e15   Arjan van de Ven   [PATCH] Unlinline...
966
  static void itimer_delete(struct k_itimer *timer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
968
  {
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
  retry_delete:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
  	spin_lock_irqsave(&timer->it_lock, flags);
becf8b5d0   Thomas Gleixner   [PATCH] hrtimer: ...
971
  	if (timer_delete_hook(timer) == TIMER_RETRY) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
974
  		unlock_timer(timer, flags);
  		goto retry_delete;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
977
978
979
  	list_del(&timer->list);
  	/*
  	 * 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...
980
  	timer->it_signal = NULL;
4b7a13042   Oleg Nesterov   posix timers: tim...
981

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
983
984
985
986
  	unlock_timer(timer, flags);
  	release_posix_timer(timer, IT_ID_SET);
  }
  
  /*
25f407f0b   Roland McGrath   [PATCH] Call exit...
987
   * This is called by do_exit or de_thread, only when there are no more
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
988
989
990
991
992
993
994
995
996
997
998
   * 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...
999
1000
  SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
  		const struct timespec __user *, tp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1001
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1002
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1003
  	struct timespec64 new_tp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004

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

5c4994102   Deepa Dinamani   posix-timers: Use...
1008
  	if (get_timespec64(&new_tp, tp))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1009
  		return -EFAULT;
5c4994102   Deepa Dinamani   posix-timers: Use...
1010
  	return kc->clock_set(which_clock, &new_tp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011
  }
362e9c07c   Heiko Carstens   [CVE-2009-0029] S...
1012
1013
  SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
  		struct 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 kernel_tp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
  	int error;
422857776   Thomas Gleixner   posix-timers: Con...
1018
  	if (!kc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  		return -EINVAL;
422857776   Thomas Gleixner   posix-timers: Con...
1020

5c4994102   Deepa Dinamani   posix-timers: Use...
1021
  	error = kc->clock_get(which_clock, &kernel_tp);
422857776   Thomas Gleixner   posix-timers: Con...
1022

5c4994102   Deepa Dinamani   posix-timers: Use...
1023
  	if (!error && put_timespec64(&kernel_tp, tp))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
1025
1026
  		error = -EFAULT;
  
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1027
  }
f1f1d5ebd   Richard Cochran   posix-timers: Int...
1028
1029
1030
  SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
  		struct timex __user *, utx)
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1031
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
f1f1d5ebd   Richard Cochran   posix-timers: Int...
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
  	struct timex ktx;
  	int err;
  
  	if (!kc)
  		return -EINVAL;
  	if (!kc->clock_adj)
  		return -EOPNOTSUPP;
  
  	if (copy_from_user(&ktx, utx, sizeof(ktx)))
  		return -EFAULT;
  
  	err = kc->clock_adj(which_clock, &ktx);
f0dbe81f0   Miroslav Lichvar   posix-timers: Fix...
1044
  	if (err >= 0 && copy_to_user(utx, &ktx, sizeof(ktx)))
f1f1d5ebd   Richard Cochran   posix-timers: Int...
1045
1046
1047
1048
  		return -EFAULT;
  
  	return err;
  }
d822cdcce   Al Viro   posix-timers: Mov...
1049
1050
1051
1052
  SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
  		struct timespec __user *, tp)
  {
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1053
  	struct timespec64 rtn_tp;
d822cdcce   Al Viro   posix-timers: Mov...
1054
1055
1056
1057
  	int error;
  
  	if (!kc)
  		return -EINVAL;
5c4994102   Deepa Dinamani   posix-timers: Use...
1058
  	error = kc->clock_getres(which_clock, &rtn_tp);
d822cdcce   Al Viro   posix-timers: Mov...
1059

5c4994102   Deepa Dinamani   posix-timers: Use...
1060
  	if (!error && tp && put_timespec64(&rtn_tp, tp))
d822cdcce   Al Viro   posix-timers: Mov...
1061
1062
1063
1064
  		error = -EFAULT;
  
  	return error;
  }
3a4d44b61   Al Viro   ntp: Move adjtime...
1065
  #ifdef CONFIG_COMPAT
d822cdcce   Al Viro   posix-timers: Mov...
1066
1067
1068
1069
  COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
  		       struct compat_timespec __user *, tp)
  {
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1070
  	struct timespec64 ts;
d822cdcce   Al Viro   posix-timers: Mov...
1071
1072
1073
  
  	if (!kc || !kc->clock_set)
  		return -EINVAL;
5c4994102   Deepa Dinamani   posix-timers: Use...
1074
  	if (compat_get_timespec64(&ts, tp))
d822cdcce   Al Viro   posix-timers: Mov...
1075
  		return -EFAULT;
5c4994102   Deepa Dinamani   posix-timers: Use...
1076
  	return kc->clock_set(which_clock, &ts);
d822cdcce   Al Viro   posix-timers: Mov...
1077
1078
1079
1080
1081
1082
  }
  
  COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
  		       struct compat_timespec __user *, tp)
  {
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1083
1084
  	struct timespec64 ts;
  	int err;
d822cdcce   Al Viro   posix-timers: Mov...
1085
1086
1087
  
  	if (!kc)
  		return -EINVAL;
5c4994102   Deepa Dinamani   posix-timers: Use...
1088
  	err = kc->clock_get(which_clock, &ts);
d822cdcce   Al Viro   posix-timers: Mov...
1089

5c4994102   Deepa Dinamani   posix-timers: Use...
1090
1091
  	if (!err && compat_put_timespec64(&ts, tp))
  		err = -EFAULT;
d822cdcce   Al Viro   posix-timers: Mov...
1092

5c4994102   Deepa Dinamani   posix-timers: Use...
1093
  	return err;
d822cdcce   Al Viro   posix-timers: Mov...
1094
  }
3a4d44b61   Al Viro   ntp: Move adjtime...
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
  COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
  		       struct compat_timex __user *, utp)
  {
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
  	struct timex ktx;
  	int err;
  
  	if (!kc)
  		return -EINVAL;
  	if (!kc->clock_adj)
  		return -EOPNOTSUPP;
  
  	err = compat_get_timex(&ktx, utp);
  	if (err)
  		return err;
  
  	err = kc->clock_adj(which_clock, &ktx);
  
  	if (err >= 0)
  		err = compat_put_timex(utp, &ktx);
  
  	return err;
  }
3a4d44b61   Al Viro   ntp: Move adjtime...
1118

d822cdcce   Al Viro   posix-timers: Mov...
1119
1120
  COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
  		       struct compat_timespec __user *, tp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1121
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1122
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
5c4994102   Deepa Dinamani   posix-timers: Use...
1123
1124
  	struct timespec64 ts;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1125

e5e542eea   Thomas Gleixner   posix-timers: Con...
1126
  	if (!kc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
  		return -EINVAL;
5c4994102   Deepa Dinamani   posix-timers: Use...
1128
1129
1130
  	err = kc->clock_getres(which_clock, &ts);
  	if (!err && tp && compat_put_timespec64(&ts, tp))
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131

5c4994102   Deepa Dinamani   posix-timers: Use...
1132
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1133
  }
5c4994102   Deepa Dinamani   posix-timers: Use...
1134

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137
  /*
97735f25d   Thomas Gleixner   [PATCH] hrtimer: ...
1138
1139
1140
   * nanosleep for monotonic and realtime clocks
   */
  static int common_nsleep(const clockid_t which_clock, int flags,
938e7cf2d   Thomas Gleixner   posix-timers: Mak...
1141
  			 const struct timespec64 *rqtp)
97735f25d   Thomas Gleixner   [PATCH] hrtimer: ...
1142
  {
938e7cf2d   Thomas Gleixner   posix-timers: Mak...
1143
  	return hrtimer_nanosleep(rqtp, flags & TIMER_ABSTIME ?
080344b98   Oleg Nesterov   hrtimer: fix *rmt...
1144
1145
  				 HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
  				 which_clock);
97735f25d   Thomas Gleixner   [PATCH] hrtimer: ...
1146
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1147

362e9c07c   Heiko Carstens   [CVE-2009-0029] S...
1148
1149
1150
  SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
  		const struct timespec __user *, rqtp,
  		struct timespec __user *, rmtp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1151
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1152
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1153
  	struct timespec64 t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1154

a5cd28801   Thomas Gleixner   posix-timers: Con...
1155
  	if (!kc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156
  		return -EINVAL;
a5cd28801   Thomas Gleixner   posix-timers: Con...
1157
1158
  	if (!kc->nsleep)
  		return -ENANOSLEEP_NOTSUP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159

c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1160
  	if (get_timespec64(&t, rqtp))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
  		return -EFAULT;
c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1162
  	if (!timespec64_valid(&t))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1163
  		return -EINVAL;
99e6c0e6e   Al Viro   posix-timers: Sto...
1164
1165
  	if (flags & TIMER_ABSTIME)
  		rmtp = NULL;
edbeda463   Al Viro   time/posix-timers...
1166
  	current->restart_block.nanosleep.type = rmtp ? TT_NATIVE : TT_NONE;
99e6c0e6e   Al Viro   posix-timers: Sto...
1167
  	current->restart_block.nanosleep.rmtp = rmtp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168

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

edbeda463   Al Viro   time/posix-timers...
1172
1173
1174
1175
  #ifdef CONFIG_COMPAT
  COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
  		       struct compat_timespec __user *, rqtp,
  		       struct compat_timespec __user *, rmtp)
1711ef386   Toyo Abe   [PATCH] posix-tim...
1176
  {
d3ba5a9a3   Christoph Hellwig   posix-timers: Mak...
1177
  	const struct k_clock *kc = clockid_to_kclock(which_clock);
c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1178
  	struct timespec64 t;
59bd5bc24   Thomas Gleixner   posix-timers: Con...
1179

edbeda463   Al Viro   time/posix-timers...
1180
  	if (!kc)
59bd5bc24   Thomas Gleixner   posix-timers: Con...
1181
  		return -EINVAL;
edbeda463   Al Viro   time/posix-timers...
1182
1183
  	if (!kc->nsleep)
  		return -ENANOSLEEP_NOTSUP;
c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1184
  	if (compat_get_timespec64(&t, rqtp))
edbeda463   Al Viro   time/posix-timers...
1185
  		return -EFAULT;
1711ef386   Toyo Abe   [PATCH] posix-tim...
1186

c0edd7c9a   Deepa Dinamani   nanosleep: Use ge...
1187
  	if (!timespec64_valid(&t))
edbeda463   Al Viro   time/posix-timers...
1188
1189
1190
1191
1192
  		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...
1193
  	return kc->nsleep(which_clock, flags, &t);
1711ef386   Toyo Abe   [PATCH] posix-tim...
1194
  }
edbeda463   Al Viro   time/posix-timers...
1195
  #endif
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1196
1197
  
  static const struct k_clock clock_realtime = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1198
1199
1200
1201
1202
  	.clock_getres		= posix_get_hrtimer_res,
  	.clock_get		= posix_clock_realtime_get,
  	.clock_set		= posix_clock_realtime_set,
  	.clock_adj		= posix_clock_realtime_adj,
  	.nsleep			= common_nsleep,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1203
1204
1205
1206
1207
1208
1209
1210
1211
  	.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,
  	.timer_arm		= common_hrtimer_arm,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1212
1213
1214
  };
  
  static const struct k_clock clock_monotonic = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1215
1216
1217
  	.clock_getres		= posix_get_hrtimer_res,
  	.clock_get		= posix_ktime_get_ts,
  	.nsleep			= common_nsleep,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1218
1219
1220
1221
1222
1223
1224
1225
1226
  	.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,
  	.timer_arm		= common_hrtimer_arm,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1227
1228
1229
  };
  
  static const struct k_clock clock_monotonic_raw = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1230
1231
  	.clock_getres		= posix_get_hrtimer_res,
  	.clock_get		= posix_get_monotonic_raw,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1232
1233
1234
  };
  
  static const struct k_clock clock_realtime_coarse = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1235
1236
  	.clock_getres		= posix_get_coarse_res,
  	.clock_get		= posix_get_realtime_coarse,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1237
1238
1239
  };
  
  static const struct k_clock clock_monotonic_coarse = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1240
1241
  	.clock_getres		= posix_get_coarse_res,
  	.clock_get		= posix_get_monotonic_coarse,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1242
1243
1244
  };
  
  static const struct k_clock clock_tai = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1245
1246
1247
  	.clock_getres		= posix_get_hrtimer_res,
  	.clock_get		= posix_get_tai,
  	.nsleep			= common_nsleep,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1248
1249
1250
1251
1252
1253
1254
1255
1256
  	.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,
  	.timer_arm		= common_hrtimer_arm,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1257
1258
1259
  };
  
  static const struct k_clock clock_boottime = {
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1260
1261
1262
  	.clock_getres		= posix_get_hrtimer_res,
  	.clock_get		= posix_get_boottime,
  	.nsleep			= common_nsleep,
eae1c4ae2   Thomas Gleixner   posix-timers: Mak...
1263
1264
1265
1266
1267
1268
1269
1270
1271
  	.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,
  	.timer_arm		= common_hrtimer_arm,
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
  };
  
  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,
  	[CLOCK_BOOTTIME]		= &clock_boottime,
  	[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)
  {
f7fbe38cc   Thomas Gleixner   posix-timers: Pro...
1290
1291
1292
  	clockid_t idx = id;
  
  	if (id < 0) {
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1293
1294
  		return (id & CLOCKFD_MASK) == CLOCKFD ?
  			&clock_posix_dynamic : &clock_posix_cpu;
f7fbe38cc   Thomas Gleixner   posix-timers: Pro...
1295
  	}
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1296

f7fbe38cc   Thomas Gleixner   posix-timers: Pro...
1297
  	if (id >= ARRAY_SIZE(posix_clocks))
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1298
  		return NULL;
f7fbe38cc   Thomas Gleixner   posix-timers: Pro...
1299
1300
  
  	return posix_clocks[array_index_nospec(idx, ARRAY_SIZE(posix_clocks))];
6631fa12c   Thomas Gleixner   posix-timers: Avo...
1301
  }