Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
361833ef
Commit
361833ef
authored
Jul 14, 2008
by
Ingo Molnar
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'sched/clock' into sched/devel
parents
54ef76f3
c300ba25
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
123 additions
and
20 deletions
+123
-20
include/linux/sched.h
include/linux/sched.h
+16
-1
kernel/sched_clock.c
kernel/sched_clock.c
+105
-19
kernel/time/tick-sched.c
kernel/time/tick-sched.c
+2
-0
No files found.
include/linux/sched.h
View file @
361833ef
...
@@ -1558,13 +1558,28 @@ static inline void sched_clock_idle_sleep_event(void)
...
@@ -1558,13 +1558,28 @@ static inline void sched_clock_idle_sleep_event(void)
static
inline
void
sched_clock_idle_wakeup_event
(
u64
delta_ns
)
static
inline
void
sched_clock_idle_wakeup_event
(
u64
delta_ns
)
{
{
}
}
#else
#ifdef CONFIG_NO_HZ
static
inline
void
sched_clock_tick_stop
(
int
cpu
)
{
}
static
inline
void
sched_clock_tick_start
(
int
cpu
)
{
}
#endif
#else
/* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
extern
void
sched_clock_init
(
void
);
extern
void
sched_clock_init
(
void
);
extern
u64
sched_clock_cpu
(
int
cpu
);
extern
u64
sched_clock_cpu
(
int
cpu
);
extern
void
sched_clock_tick
(
void
);
extern
void
sched_clock_tick
(
void
);
extern
void
sched_clock_idle_sleep_event
(
void
);
extern
void
sched_clock_idle_sleep_event
(
void
);
extern
void
sched_clock_idle_wakeup_event
(
u64
delta_ns
);
extern
void
sched_clock_idle_wakeup_event
(
u64
delta_ns
);
#ifdef CONFIG_NO_HZ
extern
void
sched_clock_tick_stop
(
int
cpu
);
extern
void
sched_clock_tick_start
(
int
cpu
);
#endif
#endif
#endif
/* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
/*
/*
* For kernel-internal use: high-speed (but slightly incorrect) per-cpu
* For kernel-internal use: high-speed (but slightly incorrect) per-cpu
...
...
kernel/sched_clock.c
View file @
361833ef
...
@@ -3,6 +3,9 @@
...
@@ -3,6 +3,9 @@
*
*
* Copyright (C) 2008 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
* Copyright (C) 2008 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
*
*
* Updates and enhancements:
* Copyright (C) 2008 Red Hat, Inc. Steven Rostedt <srostedt@redhat.com>
*
* Based on code by:
* Based on code by:
* Ingo Molnar <mingo@redhat.com>
* Ingo Molnar <mingo@redhat.com>
* Guillaume Chazarain <guichaz@gmail.com>
* Guillaume Chazarain <guichaz@gmail.com>
...
@@ -32,6 +35,11 @@
...
@@ -32,6 +35,11 @@
#ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
#ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
#define MULTI_SHIFT 15
/* Max is double, Min is 1/2 */
#define MAX_MULTI (2LL << MULTI_SHIFT)
#define MIN_MULTI (1LL << (MULTI_SHIFT-1))
struct
sched_clock_data
{
struct
sched_clock_data
{
/*
/*
* Raw spinlock - this is a special case: this might be called
* Raw spinlock - this is a special case: this might be called
...
@@ -40,11 +48,15 @@ struct sched_clock_data {
...
@@ -40,11 +48,15 @@ struct sched_clock_data {
*/
*/
raw_spinlock_t
lock
;
raw_spinlock_t
lock
;
unsigned
long
prev
_jiffies
;
unsigned
long
tick
_jiffies
;
u64
prev_raw
;
u64
prev_raw
;
u64
tick_raw
;
u64
tick_raw
;
u64
tick_gtod
;
u64
tick_gtod
;
u64
clock
;
u64
clock
;
s64
multi
;
#ifdef CONFIG_NO_HZ
int
check_max
;
#endif
};
};
static
DEFINE_PER_CPU_SHARED_ALIGNED
(
struct
sched_clock_data
,
sched_clock_data
);
static
DEFINE_PER_CPU_SHARED_ALIGNED
(
struct
sched_clock_data
,
sched_clock_data
);
...
@@ -71,41 +83,91 @@ void sched_clock_init(void)
...
@@ -71,41 +83,91 @@ void sched_clock_init(void)
struct
sched_clock_data
*
scd
=
cpu_sdc
(
cpu
);
struct
sched_clock_data
*
scd
=
cpu_sdc
(
cpu
);
scd
->
lock
=
(
raw_spinlock_t
)
__RAW_SPIN_LOCK_UNLOCKED
;
scd
->
lock
=
(
raw_spinlock_t
)
__RAW_SPIN_LOCK_UNLOCKED
;
scd
->
prev
_jiffies
=
now_jiffies
;
scd
->
tick
_jiffies
=
now_jiffies
;
scd
->
prev_raw
=
0
;
scd
->
prev_raw
=
0
;
scd
->
tick_raw
=
0
;
scd
->
tick_raw
=
0
;
scd
->
tick_gtod
=
ktime_now
;
scd
->
tick_gtod
=
ktime_now
;
scd
->
clock
=
ktime_now
;
scd
->
clock
=
ktime_now
;
scd
->
multi
=
1
<<
MULTI_SHIFT
;
#ifdef CONFIG_NO_HZ
scd
->
check_max
=
1
;
#endif
}
}
sched_clock_running
=
1
;
sched_clock_running
=
1
;
}
}
#ifdef CONFIG_NO_HZ
/*
* The dynamic ticks makes the delta jiffies inaccurate. This
* prevents us from checking the maximum time update.
* Disable the maximum check during stopped ticks.
*/
void
sched_clock_tick_stop
(
int
cpu
)
{
struct
sched_clock_data
*
scd
=
cpu_sdc
(
cpu
);
scd
->
check_max
=
0
;
}
void
sched_clock_tick_start
(
int
cpu
)
{
struct
sched_clock_data
*
scd
=
cpu_sdc
(
cpu
);
scd
->
check_max
=
1
;
}
static
int
check_max
(
struct
sched_clock_data
*
scd
)
{
return
scd
->
check_max
;
}
#else
static
int
check_max
(
struct
sched_clock_data
*
scd
)
{
return
1
;
}
#endif
/* CONFIG_NO_HZ */
/*
/*
* update the percpu scd from the raw @now value
* update the percpu scd from the raw @now value
*
*
* - filter out backward motion
* - filter out backward motion
* - use jiffies to generate a min,max window to clip the raw values
* - use jiffies to generate a min,max window to clip the raw values
*/
*/
static
void
__update_sched_clock
(
struct
sched_clock_data
*
scd
,
u64
now
)
static
void
__update_sched_clock
(
struct
sched_clock_data
*
scd
,
u64
now
,
u64
*
time
)
{
{
unsigned
long
now_jiffies
=
jiffies
;
unsigned
long
now_jiffies
=
jiffies
;
long
delta_jiffies
=
now_jiffies
-
scd
->
prev
_jiffies
;
long
delta_jiffies
=
now_jiffies
-
scd
->
tick
_jiffies
;
u64
clock
=
scd
->
clock
;
u64
clock
=
scd
->
clock
;
u64
min_clock
,
max_clock
;
u64
min_clock
,
max_clock
;
s64
delta
=
now
-
scd
->
prev_raw
;
s64
delta
=
now
-
scd
->
prev_raw
;
WARN_ON_ONCE
(
!
irqs_disabled
());
WARN_ON_ONCE
(
!
irqs_disabled
());
min_clock
=
scd
->
tick_gtod
+
delta_jiffies
*
TICK_NSEC
;
/*
* At schedule tick the clock can be just under the gtod. We don't
* want to push it too prematurely.
*/
min_clock
=
scd
->
tick_gtod
+
(
delta_jiffies
*
TICK_NSEC
);
if
(
min_clock
>
TICK_NSEC
)
min_clock
-=
TICK_NSEC
/
2
;
if
(
unlikely
(
delta
<
0
))
{
if
(
unlikely
(
delta
<
0
))
{
clock
++
;
clock
++
;
goto
out
;
goto
out
;
}
}
max_clock
=
min_clock
+
TICK_NSEC
;
/*
* The clock must stay within a jiffie of the gtod.
* But since we may be at the start of a jiffy or the end of one
* we add another jiffy buffer.
*/
max_clock
=
scd
->
tick_gtod
+
(
2
+
delta_jiffies
)
*
TICK_NSEC
;
delta
*=
scd
->
multi
;
delta
>>=
MULTI_SHIFT
;
if
(
unlikely
(
clock
+
delta
>
max_clock
))
{
if
(
unlikely
(
clock
+
delta
>
max_clock
)
&&
check_max
(
scd
)
)
{
if
(
clock
<
max_clock
)
if
(
clock
<
max_clock
)
clock
=
max_clock
;
clock
=
max_clock
;
else
else
...
@@ -118,9 +180,12 @@ static void __update_sched_clock(struct sched_clock_data *scd, u64 now)
...
@@ -118,9 +180,12 @@ static void __update_sched_clock(struct sched_clock_data *scd, u64 now)
if
(
unlikely
(
clock
<
min_clock
))
if
(
unlikely
(
clock
<
min_clock
))
clock
=
min_clock
;
clock
=
min_clock
;
scd
->
prev_raw
=
now
;
if
(
time
)
scd
->
prev_jiffies
=
now_jiffies
;
*
time
=
clock
;
scd
->
clock
=
clock
;
else
{
scd
->
prev_raw
=
now
;
scd
->
clock
=
clock
;
}
}
}
static
void
lock_double_clock
(
struct
sched_clock_data
*
data1
,
static
void
lock_double_clock
(
struct
sched_clock_data
*
data1
,
...
@@ -160,25 +225,30 @@ u64 sched_clock_cpu(int cpu)
...
@@ -160,25 +225,30 @@ u64 sched_clock_cpu(int cpu)
now
-=
my_scd
->
tick_raw
;
now
-=
my_scd
->
tick_raw
;
now
+=
scd
->
tick_raw
;
now
+=
scd
->
tick_raw
;
now
-
=
my_scd
->
tick_gtod
;
now
+
=
my_scd
->
tick_gtod
;
now
+
=
scd
->
tick_gtod
;
now
-
=
scd
->
tick_gtod
;
__raw_spin_unlock
(
&
my_scd
->
lock
);
__raw_spin_unlock
(
&
my_scd
->
lock
);
__update_sched_clock
(
scd
,
now
,
&
clock
);
__raw_spin_unlock
(
&
scd
->
lock
);
}
else
{
}
else
{
__raw_spin_lock
(
&
scd
->
lock
);
__raw_spin_lock
(
&
scd
->
lock
);
__update_sched_clock
(
scd
,
now
,
NULL
);
clock
=
scd
->
clock
;
__raw_spin_unlock
(
&
scd
->
lock
);
}
}
__update_sched_clock
(
scd
,
now
);
clock
=
scd
->
clock
;
__raw_spin_unlock
(
&
scd
->
lock
);
return
clock
;
return
clock
;
}
}
void
sched_clock_tick
(
void
)
void
sched_clock_tick
(
void
)
{
{
struct
sched_clock_data
*
scd
=
this_scd
();
struct
sched_clock_data
*
scd
=
this_scd
();
unsigned
long
now_jiffies
=
jiffies
;
s64
mult
,
delta_gtod
,
delta_raw
;
u64
now
,
now_gtod
;
u64
now
,
now_gtod
;
if
(
unlikely
(
!
sched_clock_running
))
if
(
unlikely
(
!
sched_clock_running
))
...
@@ -186,18 +256,33 @@ void sched_clock_tick(void)
...
@@ -186,18 +256,33 @@ void sched_clock_tick(void)
WARN_ON_ONCE
(
!
irqs_disabled
());
WARN_ON_ONCE
(
!
irqs_disabled
());
now
=
sched_clock
();
now_gtod
=
ktime_to_ns
(
ktime_get
());
now_gtod
=
ktime_to_ns
(
ktime_get
());
now
=
sched_clock
();
__raw_spin_lock
(
&
scd
->
lock
);
__raw_spin_lock
(
&
scd
->
lock
);
__update_sched_clock
(
scd
,
now
);
__update_sched_clock
(
scd
,
now
,
NULL
);
/*
/*
* update tick_gtod after __update_sched_clock() because that will
* update tick_gtod after __update_sched_clock() because that will
* already observe 1 new jiffy; adding a new tick_gtod to that would
* already observe 1 new jiffy; adding a new tick_gtod to that would
* increase the clock 2 jiffies.
* increase the clock 2 jiffies.
*/
*/
delta_gtod
=
now_gtod
-
scd
->
tick_gtod
;
delta_raw
=
now
-
scd
->
tick_raw
;
if
((
long
)
delta_raw
>
0
)
{
mult
=
delta_gtod
<<
MULTI_SHIFT
;
do_div
(
mult
,
delta_raw
);
scd
->
multi
=
mult
;
if
(
scd
->
multi
>
MAX_MULTI
)
scd
->
multi
=
MAX_MULTI
;
else
if
(
scd
->
multi
<
MIN_MULTI
)
scd
->
multi
=
MIN_MULTI
;
}
else
scd
->
multi
=
1
<<
MULTI_SHIFT
;
scd
->
tick_raw
=
now
;
scd
->
tick_raw
=
now
;
scd
->
tick_gtod
=
now_gtod
;
scd
->
tick_gtod
=
now_gtod
;
scd
->
tick_jiffies
=
now_jiffies
;
__raw_spin_unlock
(
&
scd
->
lock
);
__raw_spin_unlock
(
&
scd
->
lock
);
}
}
...
@@ -227,6 +312,7 @@ void sched_clock_idle_wakeup_event(u64 delta_ns)
...
@@ -227,6 +312,7 @@ void sched_clock_idle_wakeup_event(u64 delta_ns)
__raw_spin_lock
(
&
scd
->
lock
);
__raw_spin_lock
(
&
scd
->
lock
);
scd
->
prev_raw
=
now
;
scd
->
prev_raw
=
now
;
scd
->
clock
+=
delta_ns
;
scd
->
clock
+=
delta_ns
;
scd
->
multi
=
1
<<
MULTI_SHIFT
;
__raw_spin_unlock
(
&
scd
->
lock
);
__raw_spin_unlock
(
&
scd
->
lock
);
touch_softlockup_watchdog
();
touch_softlockup_watchdog
();
...
...
kernel/time/tick-sched.c
View file @
361833ef
...
@@ -276,6 +276,7 @@ void tick_nohz_stop_sched_tick(void)
...
@@ -276,6 +276,7 @@ void tick_nohz_stop_sched_tick(void)
ts
->
tick_stopped
=
1
;
ts
->
tick_stopped
=
1
;
ts
->
idle_jiffies
=
last_jiffies
;
ts
->
idle_jiffies
=
last_jiffies
;
rcu_enter_nohz
();
rcu_enter_nohz
();
sched_clock_tick_stop
(
cpu
);
}
}
/*
/*
...
@@ -375,6 +376,7 @@ void tick_nohz_restart_sched_tick(void)
...
@@ -375,6 +376,7 @@ void tick_nohz_restart_sched_tick(void)
select_nohz_load_balancer
(
0
);
select_nohz_load_balancer
(
0
);
now
=
ktime_get
();
now
=
ktime_get
();
tick_do_update_jiffies64
(
now
);
tick_do_update_jiffies64
(
now
);
sched_clock_tick_start
(
cpu
);
cpu_clear
(
cpu
,
nohz_cpu_mask
);
cpu_clear
(
cpu
,
nohz_cpu_mask
);
/*
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment