Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
_Walt
cloud-kernel
提交
56e6a081
cloud-kernel
项目概览
_Walt
/
cloud-kernel
与 Fork 源项目一致
Fork自
openanolis / cloud-kernel
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
56e6a081
编写于
8月 21, 2012
作者:
T
Tejun Heo
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'timers/core' of
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
into for-3.7
上级
3b07e9ca
c5f66e99
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
114 addition
and
159 deletion
+114
-159
include/linux/timer.h
include/linux/timer.h
+65
-100
kernel/timer.c
kernel/timer.c
+49
-59
未找到文件。
include/linux/timer.h
浏览文件 @
56e6a081
...
@@ -49,147 +49,112 @@ extern struct tvec_base boot_tvec_bases;
...
@@ -49,147 +49,112 @@ extern struct tvec_base boot_tvec_bases;
#endif
#endif
/*
/*
* Note that all tvec_bases are 2 byte aligned and lower bit of
* Note that all tvec_bases are at least 4 byte aligned and lower two bits
* base in timer_list is guaranteed to be zero. Use the LSB to
* of base in timer_list is guaranteed to be zero. Use them for flags.
* indicate whether the timer is deferrable.
*
*
* A deferrable timer will work normally when the system is busy, but
* A deferrable timer will work normally when the system is busy, but
* will not cause a CPU to come out of idle just to service it; instead,
* will not cause a CPU to come out of idle just to service it; instead,
* the timer will be serviced when the CPU eventually wakes up with a
* the timer will be serviced when the CPU eventually wakes up with a
* subsequent non-deferrable timer.
* subsequent non-deferrable timer.
*
* An irqsafe timer is executed with IRQ disabled and it's safe to wait for
* the completion of the running instance from IRQ handlers, for example,
* by calling del_timer_sync().
*
* Note: The irq disabled callback execution is a special case for
* workqueue locking issues. It's not meant for executing random crap
* with interrupts disabled. Abuse is monitored!
*/
*/
#define TBASE_DEFERRABLE_FLAG (0x1)
#define TIMER_DEFERRABLE 0x1LU
#define TIMER_IRQSAFE 0x2LU
#define TIMER_INITIALIZER(_function, _expires, _data) { \
#define TIMER_FLAG_MASK 0x3LU
#define __TIMER_INITIALIZER(_function, _expires, _data, _flags) { \
.entry = { .prev = TIMER_ENTRY_STATIC }, \
.entry = { .prev = TIMER_ENTRY_STATIC }, \
.function = (_function), \
.function = (_function), \
.expires = (_expires), \
.expires = (_expires), \
.data = (_data), \
.data = (_data), \
.base =
&boot_tvec_bases,
\
.base =
(void *)((unsigned long)&boot_tvec_bases + (_flags)),
\
.slack = -1, \
.slack = -1, \
__TIMER_LOCKDEP_MAP_INITIALIZER( \
__TIMER_LOCKDEP_MAP_INITIALIZER( \
__FILE__ ":" __stringify(__LINE__)) \
__FILE__ ":" __stringify(__LINE__)) \
}
}
#define T
BASE_MAKE_DEFERRED(ptr) ((struct tvec_base *
) \
#define T
IMER_INITIALIZER(_function, _expires, _data
) \
((unsigned char *)(ptr) + TBASE_DEFERRABLE_FLAG)
)
__TIMER_INITIALIZER((_function), (_expires), (_data), 0
)
#define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) {\
#define TIMER_DEFERRED_INITIALIZER(_function, _expires, _data) \
.entry = { .prev = TIMER_ENTRY_STATIC }, \
__TIMER_INITIALIZER((_function), (_expires), (_data), TIMER_DEFERRABLE)
.function = (_function), \
.expires = (_expires), \
.data = (_data), \
.base = TBASE_MAKE_DEFERRED(&boot_tvec_bases), \
__TIMER_LOCKDEP_MAP_INITIALIZER( \
__FILE__ ":" __stringify(__LINE__)) \
}
#define DEFINE_TIMER(_name, _function, _expires, _data) \
#define DEFINE_TIMER(_name, _function, _expires, _data) \
struct timer_list _name = \
struct timer_list _name = \
TIMER_INITIALIZER(_function, _expires, _data)
TIMER_INITIALIZER(_function, _expires, _data)
void
init_timer_key
(
struct
timer_list
*
timer
,
void
init_timer_key
(
struct
timer_list
*
timer
,
unsigned
int
flags
,
const
char
*
name
,
const
char
*
name
,
struct
lock_class_key
*
key
);
struct
lock_class_key
*
key
);
void
init_timer_deferrable_key
(
struct
timer_list
*
timer
,
#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
const
char
*
name
,
extern
void
init_timer_on_stack_key
(
struct
timer_list
*
timer
,
struct
lock_class_key
*
key
);
unsigned
int
flags
,
const
char
*
name
,
struct
lock_class_key
*
key
);
extern
void
destroy_timer_on_stack
(
struct
timer_list
*
timer
);
#else
static
inline
void
destroy_timer_on_stack
(
struct
timer_list
*
timer
)
{
}
static
inline
void
init_timer_on_stack_key
(
struct
timer_list
*
timer
,
unsigned
int
flags
,
const
char
*
name
,
struct
lock_class_key
*
key
)
{
init_timer_key
(
timer
,
flags
,
name
,
key
);
}
#endif
#ifdef CONFIG_LOCKDEP
#ifdef CONFIG_LOCKDEP
#define
init_timer(timer)
\
#define
__init_timer(_timer, _flags)
\
do { \
do { \
static struct lock_class_key __key; \
static struct lock_class_key __key; \
init_timer_key((
timer), #timer, &__key);
\
init_timer_key((
_timer), (_flags), #_timer, &__key);
\
} while (0)
} while (0)
#define
init_timer_deferrable(timer)
\
#define
__init_timer_on_stack(_timer, _flags)
\
do { \
do { \
static struct lock_class_key __key; \
static struct lock_class_key __key; \
init_timer_
deferrable_key((timer), #timer, &__key);
\
init_timer_
on_stack_key((_timer), (_flags), #_timer, &__key);
\
} while (0)
} while (0)
#else
#define __init_timer(_timer, _flags) \
init_timer_key((_timer), (_flags), NULL, NULL)
#define __init_timer_on_stack(_timer, _flags) \
init_timer_on_stack_key((_timer), (_flags), NULL, NULL)
#endif
#define init_timer(timer) \
__init_timer((timer), 0)
#define init_timer_deferrable(timer) \
__init_timer((timer), TIMER_DEFERRABLE)
#define init_timer_on_stack(timer) \
#define init_timer_on_stack(timer) \
__init_timer_on_stack((timer), 0)
#define __setup_timer(_timer, _fn, _data, _flags) \
do { \
do { \
static struct lock_class_key __key; \
__init_timer((_timer), (_flags)); \
init_timer_on_stack_key((timer), #timer, &__key); \
(_timer)->function = (_fn); \
(_timer)->data = (_data); \
} while (0)
} while (0)
#define
setup_timer(timer, fn, data)
\
#define
__setup_timer_on_stack(_timer, _fn, _data, _flags)
\
do { \
do { \
static struct lock_class_key __key; \
__init_timer_on_stack((_timer), (_flags)); \
setup_timer_key((timer), #timer, &__key, (fn), (data));\
(_timer)->function = (_fn); \
(_timer)->data = (_data); \
} while (0)
} while (0)
#define setup_timer(timer, fn, data) \
__setup_timer((timer), (fn), (data), 0)
#define setup_timer_on_stack(timer, fn, data) \
#define setup_timer_on_stack(timer, fn, data) \
do { \
__setup_timer_on_stack((timer), (fn), (data), 0)
static struct lock_class_key __key; \
setup_timer_on_stack_key((timer), #timer, &__key, \
(fn), (data)); \
} while (0)
#define setup_deferrable_timer_on_stack(timer, fn, data) \
#define setup_deferrable_timer_on_stack(timer, fn, data) \
do { \
__setup_timer_on_stack((timer), (fn), (data), TIMER_DEFERRABLE)
static struct lock_class_key __key; \
setup_deferrable_timer_on_stack_key((timer), #timer, \
&__key, (fn), \
(data)); \
} while (0)
#else
#define init_timer(timer)\
init_timer_key((timer), NULL, NULL)
#define init_timer_deferrable(timer)\
init_timer_deferrable_key((timer), NULL, NULL)
#define init_timer_on_stack(timer)\
init_timer_on_stack_key((timer), NULL, NULL)
#define setup_timer(timer, fn, data)\
setup_timer_key((timer), NULL, NULL, (fn), (data))
#define setup_timer_on_stack(timer, fn, data)\
setup_timer_on_stack_key((timer), NULL, NULL, (fn), (data))
#define setup_deferrable_timer_on_stack(timer, fn, data)\
setup_deferrable_timer_on_stack_key((timer), NULL, NULL, (fn), (data))
#endif
#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
extern
void
init_timer_on_stack_key
(
struct
timer_list
*
timer
,
const
char
*
name
,
struct
lock_class_key
*
key
);
extern
void
destroy_timer_on_stack
(
struct
timer_list
*
timer
);
#else
static
inline
void
destroy_timer_on_stack
(
struct
timer_list
*
timer
)
{
}
static
inline
void
init_timer_on_stack_key
(
struct
timer_list
*
timer
,
const
char
*
name
,
struct
lock_class_key
*
key
)
{
init_timer_key
(
timer
,
name
,
key
);
}
#endif
static
inline
void
setup_timer_key
(
struct
timer_list
*
timer
,
const
char
*
name
,
struct
lock_class_key
*
key
,
void
(
*
function
)(
unsigned
long
),
unsigned
long
data
)
{
timer
->
function
=
function
;
timer
->
data
=
data
;
init_timer_key
(
timer
,
name
,
key
);
}
static
inline
void
setup_timer_on_stack_key
(
struct
timer_list
*
timer
,
const
char
*
name
,
struct
lock_class_key
*
key
,
void
(
*
function
)(
unsigned
long
),
unsigned
long
data
)
{
timer
->
function
=
function
;
timer
->
data
=
data
;
init_timer_on_stack_key
(
timer
,
name
,
key
);
}
extern
void
setup_deferrable_timer_on_stack_key
(
struct
timer_list
*
timer
,
const
char
*
name
,
struct
lock_class_key
*
key
,
void
(
*
function
)(
unsigned
long
),
unsigned
long
data
);
/**
/**
* timer_pending - is a timer pending?
* timer_pending - is a timer pending?
...
...
kernel/timer.c
浏览文件 @
56e6a081
...
@@ -92,24 +92,25 @@ static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
...
@@ -92,24 +92,25 @@ static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
/* Functions below help us manage 'deferrable' flag */
/* Functions below help us manage 'deferrable' flag */
static
inline
unsigned
int
tbase_get_deferrable
(
struct
tvec_base
*
base
)
static
inline
unsigned
int
tbase_get_deferrable
(
struct
tvec_base
*
base
)
{
{
return
((
unsigned
int
)(
unsigned
long
)
base
&
T
BASE_DEFERRABLE_FLAG
);
return
((
unsigned
int
)(
unsigned
long
)
base
&
T
IMER_DEFERRABLE
);
}
}
static
inline
struct
tvec_base
*
tbase_get_bas
e
(
struct
tvec_base
*
base
)
static
inline
unsigned
int
tbase_get_irqsaf
e
(
struct
tvec_base
*
base
)
{
{
return
((
struct
tvec_base
*
)((
unsigned
long
)
base
&
~
TBASE_DEFERRABLE_FLAG
)
);
return
((
unsigned
int
)(
unsigned
long
)
base
&
TIMER_IRQSAFE
);
}
}
static
inline
void
timer_set_deferrable
(
struct
timer_list
*
timer
)
static
inline
struct
tvec_base
*
tbase_get_base
(
struct
tvec_base
*
base
)
{
{
timer
->
base
=
TBASE_MAKE_DEFERRED
(
timer
->
base
);
return
((
struct
tvec_base
*
)((
unsigned
long
)
base
&
~
TIMER_FLAG_MASK
)
);
}
}
static
inline
void
static
inline
void
timer_set_base
(
struct
timer_list
*
timer
,
struct
tvec_base
*
new_base
)
timer_set_base
(
struct
timer_list
*
timer
,
struct
tvec_base
*
new_base
)
{
{
timer
->
base
=
(
struct
tvec_base
*
)((
unsigned
long
)(
new_base
)
|
unsigned
long
flags
=
(
unsigned
long
)
timer
->
base
&
TIMER_FLAG_MASK
;
tbase_get_deferrable
(
timer
->
base
));
timer
->
base
=
(
struct
tvec_base
*
)((
unsigned
long
)(
new_base
)
|
flags
);
}
}
static
unsigned
long
round_jiffies_common
(
unsigned
long
j
,
int
cpu
,
static
unsigned
long
round_jiffies_common
(
unsigned
long
j
,
int
cpu
,
...
@@ -563,16 +564,14 @@ static inline void debug_timer_assert_init(struct timer_list *timer)
...
@@ -563,16 +564,14 @@ static inline void debug_timer_assert_init(struct timer_list *timer)
debug_object_assert_init
(
timer
,
&
timer_debug_descr
);
debug_object_assert_init
(
timer
,
&
timer_debug_descr
);
}
}
static
void
__init_timer
(
struct
timer_list
*
timer
,
static
void
do_init_timer
(
struct
timer_list
*
timer
,
unsigned
int
flags
,
const
char
*
name
,
const
char
*
name
,
struct
lock_class_key
*
key
);
struct
lock_class_key
*
key
);
void
init_timer_on_stack_key
(
struct
timer_list
*
timer
,
void
init_timer_on_stack_key
(
struct
timer_list
*
timer
,
unsigned
int
flags
,
const
char
*
name
,
const
char
*
name
,
struct
lock_class_key
*
key
)
struct
lock_class_key
*
key
)
{
{
debug_object_init_on_stack
(
timer
,
&
timer_debug_descr
);
debug_object_init_on_stack
(
timer
,
&
timer_debug_descr
);
__init_timer
(
timer
,
name
,
key
);
do_init_timer
(
timer
,
flags
,
name
,
key
);
}
}
EXPORT_SYMBOL_GPL
(
init_timer_on_stack_key
);
EXPORT_SYMBOL_GPL
(
init_timer_on_stack_key
);
...
@@ -613,12 +612,13 @@ static inline void debug_assert_init(struct timer_list *timer)
...
@@ -613,12 +612,13 @@ static inline void debug_assert_init(struct timer_list *timer)
debug_timer_assert_init
(
timer
);
debug_timer_assert_init
(
timer
);
}
}
static
void
__init_timer
(
struct
timer_list
*
timer
,
static
void
do_init_timer
(
struct
timer_list
*
timer
,
unsigned
int
flags
,
const
char
*
name
,
const
char
*
name
,
struct
lock_class_key
*
key
)
struct
lock_class_key
*
key
)
{
{
struct
tvec_base
*
base
=
__raw_get_cpu_var
(
tvec_bases
);
timer
->
entry
.
next
=
NULL
;
timer
->
entry
.
next
=
NULL
;
timer
->
base
=
__raw_get_cpu_var
(
tvec_base
s
);
timer
->
base
=
(
void
*
)((
unsigned
long
)
base
|
flag
s
);
timer
->
slack
=
-
1
;
timer
->
slack
=
-
1
;
#ifdef CONFIG_TIMER_STATS
#ifdef CONFIG_TIMER_STATS
timer
->
start_site
=
NULL
;
timer
->
start_site
=
NULL
;
...
@@ -628,22 +628,10 @@ static void __init_timer(struct timer_list *timer,
...
@@ -628,22 +628,10 @@ static void __init_timer(struct timer_list *timer,
lockdep_init_map
(
&
timer
->
lockdep_map
,
name
,
key
,
0
);
lockdep_init_map
(
&
timer
->
lockdep_map
,
name
,
key
,
0
);
}
}
void
setup_deferrable_timer_on_stack_key
(
struct
timer_list
*
timer
,
const
char
*
name
,
struct
lock_class_key
*
key
,
void
(
*
function
)(
unsigned
long
),
unsigned
long
data
)
{
timer
->
function
=
function
;
timer
->
data
=
data
;
init_timer_on_stack_key
(
timer
,
name
,
key
);
timer_set_deferrable
(
timer
);
}
EXPORT_SYMBOL_GPL
(
setup_deferrable_timer_on_stack_key
);
/**
/**
* init_timer_key - initialize a timer
* init_timer_key - initialize a timer
* @timer: the timer to be initialized
* @timer: the timer to be initialized
* @flags: timer flags
* @name: name of the timer
* @name: name of the timer
* @key: lockdep class key of the fake lock used for tracking timer
* @key: lockdep class key of the fake lock used for tracking timer
* sync lock dependencies
* sync lock dependencies
...
@@ -651,24 +639,14 @@ EXPORT_SYMBOL_GPL(setup_deferrable_timer_on_stack_key);
...
@@ -651,24 +639,14 @@ EXPORT_SYMBOL_GPL(setup_deferrable_timer_on_stack_key);
* init_timer_key() must be done to a timer prior calling *any* of the
* init_timer_key() must be done to a timer prior calling *any* of the
* other timer functions.
* other timer functions.
*/
*/
void
init_timer_key
(
struct
timer_list
*
timer
,
void
init_timer_key
(
struct
timer_list
*
timer
,
unsigned
int
flags
,
const
char
*
name
,
const
char
*
name
,
struct
lock_class_key
*
key
)
struct
lock_class_key
*
key
)
{
{
debug_init
(
timer
);
debug_init
(
timer
);
__init_timer
(
timer
,
name
,
key
);
do_init_timer
(
timer
,
flags
,
name
,
key
);
}
}
EXPORT_SYMBOL
(
init_timer_key
);
EXPORT_SYMBOL
(
init_timer_key
);
void
init_timer_deferrable_key
(
struct
timer_list
*
timer
,
const
char
*
name
,
struct
lock_class_key
*
key
)
{
init_timer_key
(
timer
,
name
,
key
);
timer_set_deferrable
(
timer
);
}
EXPORT_SYMBOL
(
init_timer_deferrable_key
);
static
inline
void
detach_timer
(
struct
timer_list
*
timer
,
bool
clear_pending
)
static
inline
void
detach_timer
(
struct
timer_list
*
timer
,
bool
clear_pending
)
{
{
struct
list_head
*
entry
=
&
timer
->
entry
;
struct
list_head
*
entry
=
&
timer
->
entry
;
...
@@ -686,7 +664,7 @@ detach_expired_timer(struct timer_list *timer, struct tvec_base *base)
...
@@ -686,7 +664,7 @@ detach_expired_timer(struct timer_list *timer, struct tvec_base *base)
{
{
detach_timer
(
timer
,
true
);
detach_timer
(
timer
,
true
);
if
(
!
tbase_get_deferrable
(
timer
->
base
))
if
(
!
tbase_get_deferrable
(
timer
->
base
))
timer
->
base
->
active_timers
--
;
base
->
active_timers
--
;
}
}
static
int
detach_if_pending
(
struct
timer_list
*
timer
,
struct
tvec_base
*
base
,
static
int
detach_if_pending
(
struct
timer_list
*
timer
,
struct
tvec_base
*
base
,
...
@@ -697,7 +675,7 @@ static int detach_if_pending(struct timer_list *timer, struct tvec_base *base,
...
@@ -697,7 +675,7 @@ static int detach_if_pending(struct timer_list *timer, struct tvec_base *base,
detach_timer
(
timer
,
clear_pending
);
detach_timer
(
timer
,
clear_pending
);
if
(
!
tbase_get_deferrable
(
timer
->
base
))
{
if
(
!
tbase_get_deferrable
(
timer
->
base
))
{
timer
->
base
->
active_timers
--
;
base
->
active_timers
--
;
if
(
timer
->
expires
==
base
->
next_timer
)
if
(
timer
->
expires
==
base
->
next_timer
)
base
->
next_timer
=
base
->
timer_jiffies
;
base
->
next_timer
=
base
->
timer_jiffies
;
}
}
...
@@ -1029,14 +1007,14 @@ EXPORT_SYMBOL(try_to_del_timer_sync);
...
@@ -1029,14 +1007,14 @@ EXPORT_SYMBOL(try_to_del_timer_sync);
*
*
* Synchronization rules: Callers must prevent restarting of the timer,
* Synchronization rules: Callers must prevent restarting of the timer,
* otherwise this function is meaningless. It must not be called from
* otherwise this function is meaningless. It must not be called from
* interrupt contexts
. The caller must not hold locks which would preven
t
* interrupt contexts
unless the timer is an irqsafe one. The caller mus
t
*
completion of the timer's handler. The timer's handler must not call
*
not hold locks which would prevent completion of the timer's
*
add_timer_on(). Upon exit the timer is not queued and the handler is
*
handler. The timer's handler must not call add_timer_on(). Upon exit the
* not running on any CPU.
*
timer is not queued and the handler is
not running on any CPU.
*
*
* Note:
You must not hold locks that are held in interrupt context
* Note:
For !irqsafe timers, you must not hold locks that are held in
*
while calling this function. Even if the lock has nothing to do
*
interrupt context while calling this function. Even if the lock has
* with the timer in question. Here's why:
*
nothing to do
with the timer in question. Here's why:
*
*
* CPU0 CPU1
* CPU0 CPU1
* ---- ----
* ---- ----
...
@@ -1073,7 +1051,7 @@ int del_timer_sync(struct timer_list *timer)
...
@@ -1073,7 +1051,7 @@ int del_timer_sync(struct timer_list *timer)
* don't use it in hardirq context, because it
* don't use it in hardirq context, because it
* could lead to deadlock.
* could lead to deadlock.
*/
*/
WARN_ON
(
in_irq
());
WARN_ON
(
in_irq
()
&&
!
tbase_get_irqsafe
(
timer
->
base
)
);
for
(;;)
{
for
(;;)
{
int
ret
=
try_to_del_timer_sync
(
timer
);
int
ret
=
try_to_del_timer_sync
(
timer
);
if
(
ret
>=
0
)
if
(
ret
>=
0
)
...
@@ -1180,19 +1158,27 @@ static inline void __run_timers(struct tvec_base *base)
...
@@ -1180,19 +1158,27 @@ static inline void __run_timers(struct tvec_base *base)
while
(
!
list_empty
(
head
))
{
while
(
!
list_empty
(
head
))
{
void
(
*
fn
)(
unsigned
long
);
void
(
*
fn
)(
unsigned
long
);
unsigned
long
data
;
unsigned
long
data
;
bool
irqsafe
;
timer
=
list_first_entry
(
head
,
struct
timer_list
,
entry
);
timer
=
list_first_entry
(
head
,
struct
timer_list
,
entry
);
fn
=
timer
->
function
;
fn
=
timer
->
function
;
data
=
timer
->
data
;
data
=
timer
->
data
;
irqsafe
=
tbase_get_irqsafe
(
timer
->
base
);
timer_stats_account_timer
(
timer
);
timer_stats_account_timer
(
timer
);
base
->
running_timer
=
timer
;
base
->
running_timer
=
timer
;
detach_expired_timer
(
timer
,
base
);
detach_expired_timer
(
timer
,
base
);
spin_unlock_irq
(
&
base
->
lock
);
if
(
irqsafe
)
{
call_timer_fn
(
timer
,
fn
,
data
);
spin_unlock
(
&
base
->
lock
);
spin_lock_irq
(
&
base
->
lock
);
call_timer_fn
(
timer
,
fn
,
data
);
spin_lock
(
&
base
->
lock
);
}
else
{
spin_unlock_irq
(
&
base
->
lock
);
call_timer_fn
(
timer
,
fn
,
data
);
spin_lock_irq
(
&
base
->
lock
);
}
}
}
}
}
base
->
running_timer
=
NULL
;
base
->
running_timer
=
NULL
;
...
@@ -1800,9 +1786,13 @@ static struct notifier_block __cpuinitdata timers_nb = {
...
@@ -1800,9 +1786,13 @@ static struct notifier_block __cpuinitdata timers_nb = {
void
__init
init_timers
(
void
)
void
__init
init_timers
(
void
)
{
{
int
err
=
timer_cpu_notify
(
&
timers_nb
,
(
unsigned
long
)
CPU_UP_PREPARE
,
int
err
;
(
void
*
)(
long
)
smp_processor_id
());
/* ensure there are enough low bits for flags in timer->base pointer */
BUILD_BUG_ON
(
__alignof__
(
struct
tvec_base
)
&
TIMER_FLAG_MASK
);
err
=
timer_cpu_notify
(
&
timers_nb
,
(
unsigned
long
)
CPU_UP_PREPARE
,
(
void
*
)(
long
)
smp_processor_id
());
init_timer_stats
();
init_timer_stats
();
BUG_ON
(
err
!=
NOTIFY_OK
);
BUG_ON
(
err
!=
NOTIFY_OK
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录