Reworked RTC layer & Alarm timers
Subsystems (4)
cover Reworked RTC layer & Alarm timers
So this patchset has gotten minimal feedback, so I wanted to send it out again for another chance at feedback and consideration for partial inclusion.
The first 4 patches rework the generic RTC code adding a abstracted timerlist layer which allows the kernel to multiplex multiple event on a single RTC device. These patches haven't changed much since mid-october, so I'd like to start pushing for them to be queued for testing to be included in 2.6.38.
Alessandro: Unless you object, I'll likely push these changes upstream through Thomas. If you'd prefer to be the path, please let me know.
The last patch is the Android-inspired alarm timers infrastructure. This is still in development, and I'd really like to get Arve's input as well as other android dev's input so we can try to make sure the proposed interface will suffice for Android.
For now I've also dropped the dynamic clockid and direct RTC posix clock interface patches, as Richard's dynamic clock device code is still in-progress. I'll revisit the that interface later once Richard's code is more settled.
John Stultz (5):
Introduce timerlist infrastructure.
hrtimers: Convert hrtimers to use timerlist infrastructure
RTC: Rework RTC code to use timerlist for events
RTC: Remove UIE emulation
[RFC] Introduce Alarm (hybrid) timers
drivers/rtc/class.c | 13 + drivers/rtc/interface.c | 574 ++++++++++++++++++++++--------------- drivers/rtc/rtc-dev.c | 104 ------- drivers/rtc/rtc-lib.c | 26 ++ include/linux/alarmtimer.h | 30 ++ include/linux/hrtimer.h | 32 +-- include/linux/posix-timers.h | 2 + include/linux/rtc.h | 51 +++- include/linux/time.h | 2 + include/linux/timerlist.h | 37 +++ kernel/hrtimer.c | 86 ++---- kernel/time/Makefile | 2 +- kernel/time/alarmtimer.c | 657 ++++++++++++++++++++++++++++++++++++++++++ kernel/time/timer_list.c | 8 +- lib/Makefile | 2 +- lib/timerlist.c | 115 ++++++++ 16 files changed, 1318 insertions(+), 423 deletions(-) create mode 100644 include/linux/alarmtimer.h create mode 100644 include/linux/timerlist.h create mode 100644 kernel/time/alarmtimer.c create mode 100644 lib/timerlist.c
Signature · 1 line
1.7.3.2.146.gca209
PATCH 1/5 Introduce timerlist infrastructure.
The timerlist infrastructure is a thin layer over the rbtree code that implements a simple list of timers sorted by an expires value, and a getnext function that provides a pointer to the earliest timer.
This infrastructure allows drivers and other kernel infrastructure to easily implement timers without duplicating code.
--- include/linux/timerlist.h | 37 ++++++++++++++ lib/Makefile | 2 +- lib/timerlist.c | 115 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 1 deletions(-) create mode 100644 include/linux/timerlist.h create mode 100644 lib/timerlist.c
include/linux/timerlist.h new file +37 -0
@@ -0,0 +1,37 @@ +#ifndef _LINUX_TIMERLIST_H +#define _LINUX_TIMERLIST_H + +#include <linux/rbtree.h> +#include <linux/ktime.h> + + +struct timerlist_node { +struct rb_node node; +ktime_t expires; +}; + +struct timerlist_head { +struct rb_root head; +struct timerlist_node *next; +}; + + +extern void timerlist_add (struct timerlist_head *head, +struct timerlist_node *node); +extern void timerlist_del (struct timerlist_head *head, +struct timerlist_node *node); +extern struct timerlist_node *timerlist_getnext (struct timerlist_head *head); +extern struct timerlist_node *timerlist_iterate_next ( +struct timerlist_node *node); + +static inline void timerlist_init (struct timerlist_node *node) +{ +RB_CLEAR_NODE (&node->node); +} + +static inline void timerlist_init_head (struct timerlist_head *head) +{ + head->head =RB_ROOT ; + head->next =NULL ; +} +#endif /* _LINUX_TIMERLIST_H */
lib/Makefile +1 -1
@@ -8,7 +8,7 @@ KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS)) endif lib-y := ctype.o string.o vsprintf.o cmdline.o \ - rbtree.o radix-tree.o dump_stack.o \ + rbtree.o radix-tree.o dump_stack.o timerlist.o\ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o irq_regs.o reciprocal_div.o argv_split.o \ proportions.o prio_heap.o ratelimit.o show_mem.o \
lib/timerlist.c new file +115 -0
115 lines not on this page · raw message
Signature · 1 line
1.7.3.2.146.gca209
PATCH 2/5 hrtimers: Convert hrtimers to use timerlist infrastructure
In reply to John StultzConverts the hrtimer code to use the new timerlist infrastructure
--- include/linux/hrtimer.h | 32 ++++++++--------- kernel/hrtimer.c | 86 ++++++++++++++++------------------------------ kernel/time/timer_list.c | 8 ++-- 3 files changed, 49 insertions(+), 77 deletions(-)
include/linux/hrtimer.h +15 -17
@@ -22,7 +22,7 @@#include <linux/wait.h> #include <linux/percpu.h> #include <linux/timer.h> - +#include <linux/timerlist.h> struct hrtimer_clock_base ;struct hrtimer_cpu_base ;
@@ -79,8 +79,8 @@ enum hrtimer_restart {/** * struct hrtimer - the basic hrtimer structure -* @node: red black tree node for time ordered insertion -* @_expires: the absolute expiry time in the hrtimers internal +* @node: timerlist node, which also manages node.expires, +* the absolute expiry time in the hrtimers internal * representation. The time is related to the clock on * which the timer is based. Is setup by adding * slack to the _softexpires value. For non range timers
@@ -101,8 +101,7 @@ enum hrtimer_restart {* The hrtimer structure must be initialized by hrtimer_init() */ struct hrtimer { -struct rb_node node; -ktime_t _expires; +struct timerlist_node node;ktime_t _softexpires;enum hrtimer_restart (*function)(struct hrtimer *);struct hrtimer_clock_base *base;
@@ -141,8 +140,7 @@ struct hrtimer_sleeper {struct hrtimer_clock_base {struct hrtimer_cpu_base *cpu_base;clockid_t index; -struct rb_root active; -struct rb_node *first; +struct timerlist_head active;ktime_t resolution;ktime_t (*get_time)(void );ktime_t softirq_time;
@@ -184,43 +182,43 @@ struct hrtimer_cpu_base {static inline void hrtimer_set_expires (struct hrtimer *timer,ktime_t time) { - timer->_expires = time; + timer->node.expires = time; timer->_softexpires = time; }static inline void hrtimer_set_expires_range (struct hrtimer *timer,ktime_t time,ktime_t delta) { timer->_softexpires = time; - timer->_expires =ktime_add_safe (time, delta); + timer->node.expires =ktime_add_safe (time, delta); }static inline void hrtimer_set_expires_range_ns (struct hrtimer *timer,ktime_t time,unsigned long delta) { timer->_softexpires = time; - timer->_expires =ktime_add_safe (time,ns_to_ktime (delta)); + timer->node.expires =ktime_add_safe (time,ns_to_ktime (delta)); }static inline void hrtimer_set_expires_tv64 (struct hrtimer *timer,s64 tv64) { - timer->_expires.tv64 = tv64; + timer->node.expires.tv64 = tv64; timer->_softexpires.tv64 = tv64; }static inline void hrtimer_add_expires (struct hrtimer *timer,ktime_t time) { - timer->_expires =ktime_add_safe (timer->_expires, time); + timer->node.expires =ktime_add_safe (timer->node.expires, time); timer->_softexpires =ktime_add_safe (timer->_softexpires, time); }static inline void hrtimer_add_expires_ns (struct hrtimer *timer,u64 ns) { - timer->_expires =ktime_add_ns (timer->_expires, ns); + timer->node.expires =ktime_add_ns (timer->node.expires, ns); timer->_softexpires =ktime_add_ns (timer->_softexpires, ns); }static inline ktime_t hrtimer_get_expires (const struct hrtimer *timer) { -return timer->_expires; +return timer->node.expires; }static inline ktime_t hrtimer_get_softexpires (const struct hrtimer *timer)
@@ -230,7 +228,7 @@ static inline ktime_t hrtimer_get_softexpires(const struct hrtimer *timer)static inline s64 hrtimer_get_expires_tv64 (const struct hrtimer *timer) { -return timer->_expires.tv64; +return timer->node.expires.tv64; }static inline s64 hrtimer_get_softexpires_tv64 (const struct hrtimer *timer) {
@@ -239,12 +237,12 @@ static inline s64 hrtimer_get_softexpires_tv64(const struct hrtimer *timer)static inline s64 hrtimer_get_expires_ns (const struct hrtimer *timer) { -return ktime_to_ns (timer->_expires); +return ktime_to_ns (timer->node.expires); }static inline ktime_t hrtimer_expires_remaining (const struct hrtimer *timer) { -return ktime_sub (timer->_expires, timer->base->get_time ()); +return ktime_sub (timer->node.expires, timer->base->get_time ()); }#ifdef CONFIG_HIGH_RES_TIMERS
kernel/hrtimer.c +30 -56
182 lines not on this page · raw message
kernel/time/timer_list.c +4 -4
@@ -79,26 +79,26 @@ print_active_timers(struct seq_file *m, struct hrtimer_clock_base *base, {struct hrtimer *timer, tmp;unsigned long next =0 , i; -struct rb_node *curr; +struct timerlist_node *curr;unsigned long flags; next_one: i =0 ;raw_spin_lock_irqsave (&base->cpu_base->lock, flags); - curr = base->first; + curr =timerlist_getnext (&base->active);/* * Crude but we have to do this O(N*N) thing, because * we have to unlock the base when printing: */ while (curr && i < next) { - curr =rb_next (curr); + curr =timerlist_iterate_next (curr); i++; }if (curr) { - timer = rb_entry(curr, struct hrtimer, node); + timer = container_of(curr, struct hrtimer, node); tmp = *timer;raw_spin_unlock_irqrestore (&base->cpu_base->lock, flags);
Signature · 1 line
1.7.3.2.146.gca209
PATCH 3/5 RTC: Rework RTC code to use timerlist for events
In reply to John StultzThis patch reworks a large portion of the generic RTC code to in-effect virtualize the rtc interrupt code.
The current RTC interface is very much a raw hardware interface. Via the proc, /dev/, or sysfs interfaces, applciations can set the hardware to trigger interrupts in one of three modes:
AIE: Alarm interrupt
UIE: Update interrupt (ie: once per second)
PIE: Periodic interrupt (sub-second irqs)
The problem with this interface is that it limits the RTC hardware so it can only be used by one application at a time.
The purpose of this patch is to extend the RTC code so that we can multiplex multiple applications event needs onto a single RTC device. This is done by utilizing the timerlist infrastructure to manage a list of events, which cause the RTC hardware to be programmed to fire an interrupt for the next event in the list.
In order to preserve the functionality of the exsting proc,/dev/ and sysfs interfaces, we emulate the different interrupt modes as follows:
AIE: We create a rtc_timer dedicated to AIE mode interrupts. There is only one per device, so we don't change existing interface semantics.
UIE: Again, a dedicated rtc_timer, set for periodic mode, is used to emulate UIE interrupts. Again, only one per device.
PIE: Since PIE mode interrupts fire faster then the RTC's clock read granularity, we emulate PIE mode interrupts using a hrtimer. Again, one per device.
With this patch, the rtctest.c application in Documentation/rtc.txt passes fine on x86 hardware. However, there may very well still be bugs, so greatly I'd appreciate any feedback or testing!
--- drivers/rtc/class.c | 13 + drivers/rtc/interface.c | 574 ++++++++++++++++++++++++++++------------------ drivers/rtc/rtc-lib.c | 26 +++ include/linux/rtc.h | 43 +++- 4 files changed, 426 insertions(+), 230 deletions(-)
drivers/rtc/class.c +13 -0
@@ -16,6 +16,7 @@#include <linux/kdev_t.h> #include <linux/idr.h> #include <linux/slab.h> +#include <linux/workqueue.h> #include "rtc-core.h"
@@ -152,6 +153,18 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,spin_lock_init (&rtc->irq_task_lock);init_waitqueue_head (&rtc->irq_queue); +/* Init timerlist */ +timerlist_init_head (&rtc->timerlist); +INIT_WORK (&rtc->irqwork, rtctimer_do_work); +/* Init aie timer */ +rtctimer_init (&rtc->aie_timer, rtc_aie_update_irq, (void *)rtc); +/* Init uie timer */ +rtctimer_init (&rtc->uie_rtctimer, rtc_uie_update_irq, (void *)rtc); +/* Init pie timer */ +hrtimer_init (&rtc->pie_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_REL ); + rtc->pie_timer.function = rtc_pie_update_irq; + rtc->pie_enabled =0 ; +strlcpy (rtc->name, name,RTC_DEVICE_NAME_SIZE );dev_set_name (&rtc->dev,"rtc%d" , id);
drivers/rtc/interface.c +349 -225
678 lines not on this page · raw message
drivers/rtc/rtc-lib.c +26 -0
@@ -117,4 +117,30 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) }EXPORT_SYMBOL (rtc_tm_to_time); +/* +* Convert rtc_time to ktime +*/ +ktime_t rtc_tm_to_ktime (struct rtc_time tm) +{ +time_t time; +rtc_tm_to_time (&tm, &time); +return ktime_set (time,0 ); +} + +/* +* Convert ktime to rtc_time +*/ +struct rtc_time rtc_ktime_to_tm (ktime_t kt) +{ +struct timespec ts; +struct rtc_time ret; + + ts =ktime_to_timespec (kt); +/* Round up any ns */ +if (ts.tv_nsec) + ts.tv_sec++; +rtc_time_to_tm (ts.tv_sec, &ret); +return ret; +} +MODULE_LICENSE ("GPL" );
include/linux/rtc.h +38 -5
78 lines not on this page · raw message
Signature · 1 line
1.7.3.2.146.gca209
Re: [PATCH 3/5] RTC: Rework RTC code to use timerlist for events
Quoted 2 lines · John Stultz
This patch reworks a large portion of the generic RTC code to in-effect virtualize the rtc interrupt code.
That breaks RTC on powermac which uses rtc-generic.
# hwclock select() to /dev/rtc0 to wait for clock tick timed out
Andreas.
Signature · 3 lines
Andreas Schwab, [email protected] GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."
Re: [PATCH 3/5] RTC: Rework RTC code to use timerlist for events
Quoted 9 lines · Andreas Schwab
Quoted 2 lines · John Stultz
This patch reworks a large portion of the generic RTC code to in-effect virtualize the rtc interrupt code.
That breaks RTC on powermac which uses rtc-generic.
# hwclock select() to /dev/rtc0 to wait for clock tick timed out
Thanks for the heads up! I'll see if I can get it reproduced.
-john
Re: [PATCH 3/5] RTC: Rework RTC code to use timerlist for events
In reply to Andreas SchwabQuoted 9 lines · Andreas Schwab
Quoted 2 lines · John Stultz
This patch reworks a large portion of the generic RTC code to in-effect virtualize the rtc interrupt code.
That breaks RTC on powermac which uses rtc-generic.
# hwclock select() to /dev/rtc0 to wait for clock tick timed out
Actually, can you also send strace output?
thanks
-john
Re: [PATCH 3/5] RTC: Rework RTC code to use timerlist for events
Quoted 6 lines · John Stultz
Quoted 5 lines · Andreas Schwab
Quoted 2 lines · John Stultz
This patch reworks a large portion of the generic RTC code to in-effect virtualize the rtc interrupt code.
Quoted 6 lines
Quoted 4 lines
That breaks RTC on powermac which uses rtc-generic.
# hwclock select() to /dev/rtc0 to wait for clock tick timed outActually, can you also send strace output?
ioctl(4, RTC_UIE_ON, 0) = 0select(5, [4], NULL, NULL, {5, 0}) = 0 (Timeout)write(2, "select() to /dev/rtc0 to wait fo"..., 55) = 55ioctl(4, RTC_UIE_OFF, 0) = 0
CONFIG_RTC_INTF_DEV_UIE_EMUL was never enabled, and RTC_UIE_ON returned EINVAL before, which caused hwclock to fall back to polling.
Andreas.
Signature · 3 lines
Andreas Schwab, [email protected] GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."
PATCH 4/5 RTC: Remove UIE emulation
In reply to John StultzSince we provide UIE interrupts via a rtc_timer, the old emulation code can be removed.
--- drivers/rtc/rtc-dev.c | 104 ------------------------------------------------- include/linux/rtc.h | 12 ------ 2 files changed, 0 insertions(+), 116 deletions(-)
drivers/rtc/rtc-dev.c +0 -104
@@ -46,105 +46,6 @@ static int rtc_dev_open(struct inode *inode, struct file *file)return err; } -#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL -/* -* Routine to poll RTC seconds field for change as often as possible, -* after first RTC_UIE use timer to reduce polling -*/ -static void rtc_uie_task (struct work_struct *work) -{ -struct rtc_device *rtc = - container_of(work, struct rtc_device, uie_task); -struct rtc_time tm; -int num =0 ; -int err; - - err =rtc_read_time (rtc, &tm); - -spin_lock_irq (&rtc->irq_lock); -if (rtc->stop_uie_polling || err) { - rtc->uie_task_active =0 ; - }else if (rtc->oldsecs != tm.tm_sec) { - num = (tm.tm_sec +60 - rtc->oldsecs) %60 ; - rtc->oldsecs = tm.tm_sec; - rtc->uie_timer.expires = jiffies +HZ - (HZ /10 ); - rtc->uie_timer_active =1 ; - rtc->uie_task_active =0 ; -add_timer (&rtc->uie_timer); - }else if (schedule_work (&rtc->uie_task) ==0 ) { - rtc->uie_task_active =0 ; - } -spin_unlock_irq (&rtc->irq_lock); -if (num) -rtc_update_irq (rtc, num,RTC_UF |RTC_IRQF ); -} -static void rtc_uie_timer (unsigned long data) -{ -struct rtc_device *rtc = (struct rtc_device *)data; -unsigned long flags; - -spin_lock_irqsave (&rtc->irq_lock, flags); - rtc->uie_timer_active =0 ; - rtc->uie_task_active =1 ; -if ((schedule_work (&rtc->uie_task) ==0 )) - rtc->uie_task_active =0 ; -spin_unlock_irqrestore (&rtc->irq_lock, flags); -} - -static int clear_uie (struct rtc_device *rtc) -{ -spin_lock_irq (&rtc->irq_lock); -if (rtc->uie_irq_active) { - rtc->stop_uie_polling =1 ; -if (rtc->uie_timer_active) { -spin_unlock_irq (&rtc->irq_lock); -del_timer_sync (&rtc->uie_timer); -spin_lock_irq (&rtc->irq_lock); - rtc->uie_timer_active =0 ; - } -if (rtc->uie_task_active) { -spin_unlock_irq (&rtc->irq_lock); -flush_scheduled_work (); -spin_lock_irq (&rtc->irq_lock); - } - rtc->uie_irq_active =0 ; - } -spin_unlock_irq (&rtc->irq_lock); -return 0 ; -} - -static int set_uie (struct rtc_device *rtc) -{ -struct rtc_time tm; -int err; - - err =rtc_read_time (rtc, &tm); -if (err) -return err; -spin_lock_irq (&rtc->irq_lock); -if (!rtc->uie_irq_active) { - rtc->uie_irq_active =1 ; - rtc->stop_uie_polling =0 ; - rtc->oldsecs = tm.tm_sec; - rtc->uie_task_active =1 ; -if (schedule_work (&rtc->uie_task) ==0 ) - rtc->uie_task_active =0 ; - } - rtc->irq_data =0 ; -spin_unlock_irq (&rtc->irq_lock); -return 0 ; -} - -int rtc_dev_update_irq_enable_emul (struct rtc_device *rtc,unsigned int enabled) -{ -if (enabled) -return set_uie (rtc); -else -return clear_uie (rtc); -} -EXPORT_SYMBOL (rtc_dev_update_irq_enable_emul); - -#endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ static ssize_t rtc_dev_read (struct file *file,char __user *buf,size_t count,loff_t *ppos)
@@ -493,11 +394,6 @@ void rtc_dev_prepare(struct rtc_device *rtc) rtc->dev.devt =MKDEV (MAJOR (rtc_devt), rtc->id); -#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL -INIT_WORK (&rtc->uie_task, rtc_uie_task); -setup_timer (&rtc->uie_timer, rtc_uie_timer, (unsigned long )rtc); -#endif -cdev_init (&rtc->char_dev, &rtc_dev_fops); rtc->char_dev.owner = rtc->owner; }
include/linux/rtc.h +0 -12
@@ -203,18 +203,6 @@ struct rtc_devicestruct hrtimer pie_timer;/* sub second exp, so needs hrtimer */ int pie_enabled;struct work_struct irqwork; - - -#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL -struct work_struct uie_task; -struct timer_list uie_timer; -/* Those fields are protected by rtc->irq_lock */ -unsigned int oldsecs; - unsigned int uie_irq_active:1; - unsigned int stop_uie_polling:1; - unsigned int uie_task_active:1; - unsigned int uie_timer_active:1; -#endif };#define to_rtc_device (d) container_of(d, struct rtc_device, dev)
Signature · 1 line
1.7.3.2.146.gca209
PATCH 1/1 RTC: remove Kconfig symbol for UIE emulation
The effect of changing the value of this symbol is gone since
042620a (RTC: Remove UIE emulation)
so remove symbol, too.
--- drivers/rtc/Kconfig | 12 ------------ 1 files changed, 0 insertions(+), 12 deletions(-)
drivers/rtc/Kconfig +0 -12
@@ -97,18 +97,6 @@ config RTC_INTF_DEV If unsure, say Y. -config RTC_INTF_DEV_UIE_EMUL - bool "RTC UIE emulation on dev interface" - depends on RTC_INTF_DEV - help - Provides an emulation for RTC_UIE if the underlying rtc chip - driver does not expose RTC_UIE ioctls. Those requests generate - once-per-second update interrupts, used for synchronization. - - The emulation code will read the time from the hardware - clock several times per second, please enable this option - only if you know that you really need it. - config RTC_DRV_TEST tristate "Test driver/device" help
Signature · 1 line
1.7.2.3
Re: [PATCH] RTC: remove Kconfig symbol for UIE emulation
Quoted 7 lines · Uwe Kleine-König
The effect of changing the value of this symbol is gone since
042620a (RTC: Remove UIE emulation)so remove symbol, too.
Signed-off-by Uwe Kleine-König <[email protected]>
Ah! Thanks for catching that!
RFC PATCH 5/5 Introduce Alarm (hybrid) timers
In reply to John StultzThis patch introduces a new type of hybrid timer, called alarm-timers.
Alarm-timers are similar to hrtimers, but when a system is suspended, the RTC device is set to fire when the soonest alarm timer expires.
Alarm-timers are exposed to userland via the posix clock and timers interface, using two new clockids: CLOCK_REALTIME_ALARM and CLOCK_MONOTONIC_ALARM. Both clockids behave identically to CLOCK_REALTIME and CLOCK_MONOTONIC, respectively, but timers set against the _ALARM suffixed clockids will wake the system if it is suspended.
The concept for Alarm-timers was inspired by the Android Alarm driver (by Arve Hjønnevåg) found in the Android kernel tree.
The android alarm driver was built on top of direct RTC manipulation, and also implemented its own rbtree timer code, so instead of trying to porting it over to my timerlist and RTC timer code, I just re-implemented the basic functionality roughly following the android in-kernel interface.
Another distinction is that while the in-kernel interface is pretty similar, the user-space interface for android alarm timers is via ioctls. 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).
Its possible that I've missed some subtleties of the Android alarm driver interface, and that some of the interface decisions I've made may not allow Android to use this interface directly, I'd be very interested if those details could be pointed out, and hopefully we can find a good solution to get this useful functionality upstream.
Arve: I know you're busy now, so no rush on reviewing this. I just wanted to send this out to get some early feedback if anyone else wants to comment. I look forward to your input when you are a bit less swamped.
One issue that is currently present in this version of the patch, is that I've recently implemented clock_nanosleep(), however, clock_nanosleep() calls against the _ALARM clockids do not wake the system from suspend. This is because the clock_nanosleep syscall is interrupted by suspend and restarted on resume.
Thomas: Any thoughts on how to best solve this issue?
--- include/linux/alarmtimer.h | 30 ++ include/linux/posix-timers.h | 2 + include/linux/time.h | 2 + kernel/time/Makefile | 2 +- kernel/time/alarmtimer.c | 657 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 692 insertions(+), 1 deletions(-) create mode 100644 include/linux/alarmtimer.h create mode 100644 kernel/time/alarmtimer.c
include/linux/alarmtimer.h new file +30 -0
@@ -0,0 +1,30 @@ +#ifndef _LINUX_ALARMTIMER_H +#define _LINUX_ALARMTIMER_H + +#include <linux/time.h> +#include <linux/hrtimer.h> +#include <linux/timerlist.h> +#include <linux/rtc.h> + +enum alarmtimer_type { +ALARM_REALTIME , +ALARM_MONOTONIC , + +ALARM_NUMTYPE , +}; + +struct alarm { +struct timerlist_node node; +ktime_t period; +void (*function)(struct alarm *); +enum alarmtimer_type type; +char enabled; +void *data; +}; + +void alarm_init (struct alarm *alarm,enum alarmtimer_type type, +void (*function)(struct alarm *)); +void alarm_start (struct alarm *alarm,ktime_t start,ktime_t period); +void alarm_cancel (struct alarm *alarm); + +#endif
include/linux/posix-timers.h +2 -0
@@ -4,6 +4,7 @@#include <linux/spinlock.h> #include <linux/list.h> #include <linux/sched.h> +#include <linux/alarmtimer.h> union cpu_time_count {cputime_t cpu;
@@ -63,6 +64,7 @@ struct k_itimer {unsigned long incr;unsigned long expires; } mmtimer; +struct alarm alarmtimer; } it; };
include/linux/time.h +2 -0
@@ -290,6 +290,8 @@ struct itimerval {#define CLOCK_MONOTONIC_RAW 4#define CLOCK_REALTIME_COARSE 5#define CLOCK_MONOTONIC_COARSE 6 +#define CLOCK_REALTIME_ALARM 7 +#define CLOCK_MONOTONIC_ALARM 8/* * The IDs of various hardware clocks:
kernel/time/Makefile +1 -1
@@ -1,4 +1,4 @@ -obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o timecompare.o timeconv.o +obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o timecompare.o timeconv.o alarmtimer.o obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD) += clockevents.o obj-$(CONFIG_GENERIC_CLOCKEVENTS) += tick-common.o
kernel/time/alarmtimer.c new file +657 -0
657 lines not on this page · raw message
Signature · 1 line
1.7.3.2.146.gca209
Quoted 3 lines · On Thu, 18 Nov 2010 19:12:04 -0800 John Stultz <[email protected]> wrote:
Alessandro: Unless you object, I'll likely push these changes upstream through Thomas. If you'd prefer to be the path, please let me know.
No objections here!
Signature · 6 lines
Best regards, Alessandro Zummo, Tower Technologies - Torino, Italy http://www.towertech.it