From: sboyd@codeaurora.org (Stephen Boyd)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4 04/17] sched_clock: Add support for >32 bit sched_clock
Date: Thu, 18 Jul 2013 16:21:17 -0700 [thread overview]
Message-ID: <1374189690-10810-5-git-send-email-sboyd@codeaurora.org> (raw)
In-Reply-To: <1374189690-10810-1-git-send-email-sboyd@codeaurora.org>
The ARM architected system counter has at least 56 usable bits.
Add support for counters with more than 32 bits to the generic
sched_clock implementation so we can increase the time between
wakeups due to dealing with wrap-around on these devices while
benefiting from the irqtime accounting and suspend/resume
handling that the generic sched_clock code already has. On my
system using 56 bits over 32 bits changes the wraparound time
from a few minutes to an hour. For faster running counters (GHz
range) this is even more important because we may not be able to
execute the timer in time to deal with the wraparound if only 32
bits are used.
We choose a maxsec value of 3600 seconds because we assume no
system will go idle for more than an hour. In the future we may
need to increase this value.
Note: All users should switch over to the 64-bit read function so
we can remove setup_sched_clock() in favor of sched_clock_register().
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
include/linux/sched_clock.h | 2 ++
kernel/time/sched_clock.c | 46 +++++++++++++++++++++++++++++++--------------
2 files changed, 34 insertions(+), 14 deletions(-)
diff --git a/include/linux/sched_clock.h b/include/linux/sched_clock.h
index fa7922c..eca7abe 100644
--- a/include/linux/sched_clock.h
+++ b/include/linux/sched_clock.h
@@ -15,6 +15,8 @@ static inline void sched_clock_postinit(void) { }
#endif
extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
+extern void sched_clock_register(u64 (*read)(void), int bits,
+ unsigned long rate);
extern unsigned long long (*sched_clock_func)(void);
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index a269890b..3aa83ba 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -16,11 +16,12 @@
#include <linux/hrtimer.h>
#include <linux/sched_clock.h>
#include <linux/seqlock.h>
+#include <linux/bitops.h>
struct clock_data {
ktime_t wrap_kt;
u64 epoch_ns;
- u32 epoch_cyc;
+ u64 epoch_cyc;
seqcount_t seq;
unsigned long rate;
u32 mult;
@@ -37,14 +38,25 @@ static struct clock_data cd = {
.mult = NSEC_PER_SEC / HZ,
};
-static u32 __read_mostly sched_clock_mask = 0xffffffff;
+static u64 __read_mostly sched_clock_mask;
-static u32 notrace jiffy_sched_clock_read(void)
+static u64 notrace jiffy_sched_clock_read(void)
{
- return (u32)(jiffies - INITIAL_JIFFIES);
+ /*
+ * We don't need to use get_jiffies_64 on 32-bit arches here
+ * because we register with BITS_PER_LONG
+ */
+ return (u64)(jiffies - INITIAL_JIFFIES);
+}
+
+static u32 __read_mostly (*read_sched_clock_32)(void);
+
+static u64 notrace read_sched_clock_32_wrapper(void)
+{
+ return read_sched_clock_32();
}
-static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
+static u64 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
{
@@ -54,8 +66,8 @@ static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
static unsigned long long notrace sched_clock_32(void)
{
u64 epoch_ns;
- u32 epoch_cyc;
- u32 cyc;
+ u64 epoch_cyc;
+ u64 cyc;
unsigned long seq;
if (cd.suspended)
@@ -78,7 +90,7 @@ static unsigned long long notrace sched_clock_32(void)
static void notrace update_sched_clock(void)
{
unsigned long flags;
- u32 cyc;
+ u64 cyc;
u64 ns;
cyc = read_sched_clock();
@@ -101,7 +113,8 @@ static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
return HRTIMER_RESTART;
}
-void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
+void __init sched_clock_register(u64 (*read)(void), int bits,
+ unsigned long rate)
{
unsigned long r;
u64 res, wrap;
@@ -110,14 +123,13 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
if (cd.rate > rate)
return;
- BUG_ON(bits > 32);
WARN_ON(!irqs_disabled());
read_sched_clock = read;
- sched_clock_mask = (1 << bits) - 1;
+ sched_clock_mask = CLOCKSOURCE_MASK(bits);
cd.rate = rate;
/* calculate the mult/shift to convert counter ticks to ns. */
- clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0);
+ clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600);
r = rate;
if (r >= 4000000) {
@@ -130,7 +142,7 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
r_unit = ' ';
/* calculate how many ns until we wrap */
- wrap = cyc_to_ns((1ULL << bits) - 1, cd.mult, cd.shift);
+ wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
/* calculate the ns resolution of this counter */
@@ -158,6 +170,12 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
pr_debug("Registered %pF as sched_clock source\n", read);
}
+void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
+{
+ read_sched_clock_32 = read;
+ sched_clock_register(read_sched_clock_32_wrapper, bits, rate);
+}
+
unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32;
unsigned long long notrace sched_clock(void)
@@ -172,7 +190,7 @@ void __init sched_clock_postinit(void)
* make it the final one one.
*/
if (read_sched_clock == jiffy_sched_clock_read)
- setup_sched_clock(jiffy_sched_clock_read, 32, HZ);
+ sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
update_sched_clock();
hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
next prev parent reply other threads:[~2013-07-18 23:21 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-18 23:21 [PATCH v4 00/17] 64-bit friendly generic sched_clock() Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 01/17] clocksource: Extract max nsec calculation into separate function Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 02/17] sched_clock: Use seqcount instead of rolling our own Stephen Boyd
2013-07-19 9:03 ` Will Deacon
2013-07-19 14:20 ` Nicolas Pitre
2013-07-19 14:27 ` Russell King - ARM Linux
2013-07-18 23:21 ` [PATCH v4 03/17] sched_clock: Use an hrtimer instead of timer Stephen Boyd
2013-07-22 18:21 ` John Stultz
2013-07-22 18:45 ` Stephen Boyd
2013-07-22 18:58 ` Stephen Boyd
2013-07-22 19:07 ` Russell King - ARM Linux
2013-07-22 20:48 ` John Stultz
2013-07-22 20:50 ` Stephen Boyd
2013-07-18 23:21 ` Stephen Boyd [this message]
2013-07-19 9:23 ` [PATCH v4 04/17] sched_clock: Add support for >32 bit sched_clock Baruch Siach
2013-07-19 16:29 ` Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 05/17] arch_timer: Move to generic sched_clock framework Stephen Boyd
2013-10-02 17:44 ` Will Deacon
2013-10-14 18:44 ` Kevin Hilman
2013-10-14 18:55 ` Stephen Boyd
2013-10-14 20:14 ` Kevin Hilman
2013-10-14 20:18 ` John Stultz
2013-10-14 20:14 ` John Stultz
2013-07-18 23:21 ` [PATCH v4 06/17] sched_clock: Remove sched_clock_func() hook Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 07/17] clocksource: bcm2835: Switch to sched_clock_register() Stephen Boyd
2013-07-19 19:34 ` Stephen Warren
2013-07-30 10:04 ` Daniel Lezcano
2013-07-30 16:12 ` John Stultz
2013-07-18 23:21 ` [PATCH v4 08/17] ocksource: dbx500-prcmu: " Stephen Boyd
2013-07-19 0:18 ` Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 09/17] clocksource: dw_apb_timer_of: " Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 10/17] clocksource: mxs_timer: " Stephen Boyd
2013-07-22 8:10 ` Shawn Guo
2013-07-22 16:23 ` Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 11/17] clocksource: nomadik: " Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 12/17] clocksource: samsung_pwm_timer: " Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 13/17] clocksource: tegra: " Stephen Boyd
2013-07-19 19:34 ` Stephen Warren
2013-07-18 23:21 ` [PATCH v4 14/17] clocksource: time-armada-370-xp: " Stephen Boyd
2013-08-06 9:04 ` Gregory CLEMENT
2013-07-18 23:21 ` [PATCH v4 15/17] clocksource: sirf: Switch to sched_clock_register() and use 64 bits Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 16/17] clocksource: vf_pit_timer: Switch to sched_clock_register() Stephen Boyd
2013-07-18 23:21 ` [PATCH v4 17/17] sched_clock: Deprecate setup_sched_clock() Stephen Boyd
2013-07-18 23:59 ` [PATCH v4 00/17] 64-bit friendly generic sched_clock() John Stultz
2013-07-19 0:23 ` Stephen Boyd
2013-10-02 17:47 ` Will Deacon
2013-10-02 18:02 ` John Stultz
2013-10-02 18:13 ` Will Deacon
2013-07-20 20:51 ` Linus Walleij
2013-07-22 16:24 ` Stephen Boyd
2013-07-22 17:07 ` John Stultz
2013-07-24 14:44 ` Christopher Covington
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1374189690-10810-5-git-send-email-sboyd@codeaurora.org \
--to=sboyd@codeaurora.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).