aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2011-01-11 12:54:33 -0500
committerJohn Stultz <john.stultz@linaro.org>2011-04-26 17:01:46 -0400
commit9a7adcf5c6dea63d2e47e6f6d2f7a6c9f48b9337 (patch)
tree151f7fbb135053945fc6eae99c9175e860ad343c /kernel/time
parentff3ead96d17f47ee70c294a5cc2cce9b61e82f0f (diff)
timers: Posix interface for alarm-timers
This patch exposes alarm-timers to userland via the posix clock and timers interface, using two new clockids: CLOCK_REALTIME_ALARM and CLOCK_BOOTTIME_ALARM. Both clockids behave identically to CLOCK_REALTIME and CLOCK_BOOTTIME, respectively, but timers set against the _ALARM suffixed clockids will wake the system if it is suspended. Some background can be found here: https://lwn.net/Articles/429925/ The concept for Alarm-timers was inspired by the Android Alarm driver (by Arve Hjønnevåg) found in the Android kernel tree. See: http://android.git.kernel.org/?p=kernel/common.git;a=blob;f=drivers/rtc/alarm.c;h=1250edfbdf3302f5e4ea6194847c6ef4bb7beb1c;hb=android-2.6.36 While the in-kernel interface is pretty similar between alarm-timers and Android alarm driver, the user-space interface for the Android alarm driver is via ioctls to a new char device. As mentioned above, I've instead chosen to export this functionality via the posix interface, as it seemed a little simpler and avoids creating duplicate interfaces to things like CLOCK_REALTIME and CLOCK_MONOTONIC under alternate names (ie:ANDROID_ALARM_RTC and ANDROID_ALARM_SYSTEMTIME). The semantics of the Android alarm driver are different from what this posix interface provides. For instance, threads other then the thread waiting on the Android alarm driver are able to modify the alarm being waited on. Also this interface does not allow the same wakelock semantics that the Android driver provides (ie: kernel takes a wakelock on RTC alarm-interupt, and holds it through process wakeup, and while the process runs, until the process either closes the char device or calls back in to wait on a new alarm). One potential way to implement similar semantics may be via the timerfd infrastructure, but this needs more research. There may also need to be some sort of sysfs system level policy hooks that allow alarm timers to be disabled to keep them from firing at inappropriate times (ie: laptop in a well insulated bag, mid-flight). CC: Arve Hjønnevåg <arve@android.com> CC: Thomas Gleixner <tglx@linutronix.de> CC: Alessandro Zummo <a.zummo@towertech.it> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel/time')
-rw-r--r--kernel/time/alarmtimer.c330
1 files changed, 330 insertions, 0 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 48c2ee949e61..4058ad79d55f 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -215,6 +215,21 @@ static int alarmtimer_suspend(struct device *dev)
215} 215}
216 216
217 217
218static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type)
219{
220 ktime_t delta;
221 unsigned long flags;
222 struct alarm_base *base = &alarm_bases[type];
223
224 delta = ktime_sub(absexp, base->gettime());
225
226 spin_lock_irqsave(&freezer_delta_lock, flags);
227 if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64))
228 freezer_delta = delta;
229 spin_unlock_irqrestore(&freezer_delta_lock, flags);
230}
231
232
218/************************************************************************** 233/**************************************************************************
219 * alarm kernel interface code 234 * alarm kernel interface code
220 */ 235 */
@@ -279,6 +294,309 @@ void alarm_cancel(struct alarm *alarm)
279} 294}
280 295
281 296
297/**************************************************************************
298 * alarm posix interface code
299 */
300
301/*
302 * clock2alarm - helper that converts from clockid to alarmtypes
303 * @clockid: clockid.
304 *
305 * Helper function that converts from clockids to alarmtypes
306 */
307static enum alarmtimer_type clock2alarm(clockid_t clockid)
308{
309 if (clockid == CLOCK_REALTIME_ALARM)
310 return ALARM_REALTIME;
311 if (clockid == CLOCK_BOOTTIME_ALARM)
312 return ALARM_BOOTTIME;
313 return -1;
314}
315
316/*
317 * alarm_handle_timer - Callback for posix timers
318 * @alarm: alarm that fired
319 *
320 * Posix timer callback for expired alarm timers.
321 */
322static void alarm_handle_timer(struct alarm *alarm)
323{
324 struct k_itimer *ptr = container_of(alarm, struct k_itimer,
325 it.alarmtimer);
326 if (posix_timer_event(ptr, 0) != 0)
327 ptr->it_overrun++;
328}
329
330/*
331 * alarm_clock_getres - posix getres interface
332 * @which_clock: clockid
333 * @tp: timespec to fill
334 *
335 * Returns the granularity of underlying alarm base clock
336 */
337static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp)
338{
339 clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid;
340
341 return hrtimer_get_res(baseid, tp);
342}
343
344/**
345 * alarm_clock_get - posix clock_get interface
346 * @which_clock: clockid
347 * @tp: timespec to fill.
348 *
349 * Provides the underlying alarm base time.
350 */
351static int alarm_clock_get(clockid_t which_clock, struct timespec *tp)
352{
353 struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
354
355 *tp = ktime_to_timespec(base->gettime());
356 return 0;
357}
358
359/**
360 * alarm_timer_create - posix timer_create interface
361 * @new_timer: k_itimer pointer to manage
362 *
363 * Initializes the k_itimer structure.
364 */
365static int alarm_timer_create(struct k_itimer *new_timer)
366{
367 enum alarmtimer_type type;
368 struct alarm_base *base;
369
370 if (!capable(CAP_WAKE_ALARM))
371 return -EPERM;
372
373 type = clock2alarm(new_timer->it_clock);
374 base = &alarm_bases[type];
375 alarm_init(&new_timer->it.alarmtimer, type, alarm_handle_timer);
376 return 0;
377}
378
379/**
380 * alarm_timer_get - posix timer_get interface
381 * @new_timer: k_itimer pointer
382 * @cur_setting: itimerspec data to fill
383 *
384 * Copies the itimerspec data out from the k_itimer
385 */
386static void alarm_timer_get(struct k_itimer *timr,
387 struct itimerspec *cur_setting)
388{
389 cur_setting->it_interval =
390 ktime_to_timespec(timr->it.alarmtimer.period);
391 cur_setting->it_value =
392 ktime_to_timespec(timr->it.alarmtimer.node.expires);
393 return;
394}
395
396/**
397 * alarm_timer_del - posix timer_del interface
398 * @timr: k_itimer pointer to be deleted
399 *
400 * Cancels any programmed alarms for the given timer.
401 */
402static int alarm_timer_del(struct k_itimer *timr)
403{
404 alarm_cancel(&timr->it.alarmtimer);
405 return 0;
406}
407
408/**
409 * alarm_timer_set - posix timer_set interface
410 * @timr: k_itimer pointer to be deleted
411 * @flags: timer flags
412 * @new_setting: itimerspec to be used
413 * @old_setting: itimerspec being replaced
414 *
415 * Sets the timer to new_setting, and starts the timer.
416 */
417static int alarm_timer_set(struct k_itimer *timr, int flags,
418 struct itimerspec *new_setting,
419 struct itimerspec *old_setting)
420{
421 /* Save old values */
422 old_setting->it_interval =
423 ktime_to_timespec(timr->it.alarmtimer.period);
424 old_setting->it_value =
425 ktime_to_timespec(timr->it.alarmtimer.node.expires);
426
427 /* If the timer was already set, cancel it */
428 alarm_cancel(&timr->it.alarmtimer);
429
430 /* start the timer */
431 alarm_start(&timr->it.alarmtimer,
432 timespec_to_ktime(new_setting->it_value),
433 timespec_to_ktime(new_setting->it_interval));
434 return 0;
435}
436
437/**
438 * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep
439 * @alarm: ptr to alarm that fired
440 *
441 * Wakes up the task that set the alarmtimer
442 */
443static void alarmtimer_nsleep_wakeup(struct alarm *alarm)
444{
445 struct task_struct *task = (struct task_struct *)alarm->data;
446
447 alarm->data = NULL;
448 if (task)
449 wake_up_process(task);
450}
451
452/**
453 * alarmtimer_do_nsleep - Internal alarmtimer nsleep implementation
454 * @alarm: ptr to alarmtimer
455 * @absexp: absolute expiration time
456 *
457 * Sets the alarm timer and sleeps until it is fired or interrupted.
458 */
459static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)
460{
461 alarm->data = (void *)current;
462 do {
463 set_current_state(TASK_INTERRUPTIBLE);
464 alarm_start(alarm, absexp, ktime_set(0, 0));
465 if (likely(alarm->data))
466 schedule();
467
468 alarm_cancel(alarm);
469 } while (alarm->data && !signal_pending(current));
470
471 __set_current_state(TASK_RUNNING);
472
473 return (alarm->data == NULL);
474}
475
476
477/**
478 * update_rmtp - Update remaining timespec value
479 * @exp: expiration time
480 * @type: timer type
481 * @rmtp: user pointer to remaining timepsec value
482 *
483 * Helper function that fills in rmtp value with time between
484 * now and the exp value
485 */
486static int update_rmtp(ktime_t exp, enum alarmtimer_type type,
487 struct timespec __user *rmtp)
488{
489 struct timespec rmt;
490 ktime_t rem;
491
492 rem = ktime_sub(exp, alarm_bases[type].gettime());
493
494 if (rem.tv64 <= 0)
495 return 0;
496 rmt = ktime_to_timespec(rem);
497
498 if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
499 return -EFAULT;
500
501 return 1;
502
503}
504
505/**
506 * alarm_timer_nsleep_restart - restartblock alarmtimer nsleep
507 * @restart: ptr to restart block
508 *
509 * Handles restarted clock_nanosleep calls
510 */
511static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
512{
513 enum alarmtimer_type type = restart->nanosleep.index;
514 ktime_t exp;
515 struct timespec __user *rmtp;
516 struct alarm alarm;
517 int ret = 0;
518
519 exp.tv64 = restart->nanosleep.expires;
520 alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
521
522 if (alarmtimer_do_nsleep(&alarm, exp))
523 goto out;
524
525 if (freezing(current))
526 alarmtimer_freezerset(exp, type);
527
528 rmtp = restart->nanosleep.rmtp;
529 if (rmtp) {
530 ret = update_rmtp(exp, type, rmtp);
531 if (ret <= 0)
532 goto out;
533 }
534
535
536 /* The other values in restart are already filled in */
537 ret = -ERESTART_RESTARTBLOCK;
538out:
539 return ret;
540}
541
542/**
543 * alarm_timer_nsleep - alarmtimer nanosleep
544 * @which_clock: clockid
545 * @flags: determins abstime or relative
546 * @tsreq: requested sleep time (abs or rel)
547 * @rmtp: remaining sleep time saved
548 *
549 * Handles clock_nanosleep calls against _ALARM clockids
550 */
551static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
552 struct timespec *tsreq, struct timespec __user *rmtp)
553{
554 enum alarmtimer_type type = clock2alarm(which_clock);
555 struct alarm alarm;
556 ktime_t exp;
557 int ret = 0;
558 struct restart_block *restart;
559
560 if (!capable(CAP_WAKE_ALARM))
561 return -EPERM;
562
563 alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
564
565 exp = timespec_to_ktime(*tsreq);
566 /* Convert (if necessary) to absolute time */
567 if (flags != TIMER_ABSTIME) {
568 ktime_t now = alarm_bases[type].gettime();
569 exp = ktime_add(now, exp);
570 }
571
572 if (alarmtimer_do_nsleep(&alarm, exp))
573 goto out;
574
575 if (freezing(current))
576 alarmtimer_freezerset(exp, type);
577
578 /* abs timers don't set remaining time or restart */
579 if (flags == TIMER_ABSTIME) {
580 ret = -ERESTARTNOHAND;
581 goto out;
582 }
583
584 if (rmtp) {
585 ret = update_rmtp(exp, type, rmtp);
586 if (ret <= 0)
587 goto out;
588 }
589
590 restart = &current_thread_info()->restart_block;
591 restart->fn = alarm_timer_nsleep_restart;
592 restart->nanosleep.index = type;
593 restart->nanosleep.expires = exp.tv64;
594 restart->nanosleep.rmtp = rmtp;
595 ret = -ERESTART_RESTARTBLOCK;
596
597out:
598 return ret;
599}
282 600
283/************************************************************************** 601/**************************************************************************
284 * alarmtimer initialization code 602 * alarmtimer initialization code
@@ -306,6 +624,18 @@ static int __init alarmtimer_init(void)
306{ 624{
307 int error = 0; 625 int error = 0;
308 int i; 626 int i;
627 struct k_clock alarm_clock = {
628 .clock_getres = alarm_clock_getres,
629 .clock_get = alarm_clock_get,
630 .timer_create = alarm_timer_create,
631 .timer_set = alarm_timer_set,
632 .timer_del = alarm_timer_del,
633 .timer_get = alarm_timer_get,
634 .nsleep = alarm_timer_nsleep,
635 };
636
637 posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
638 posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
309 639
310 /* Initialize alarm bases */ 640 /* Initialize alarm bases */
311 alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME; 641 alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;