Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
982d0894
提交
982d0894
6月 24, 2011
创建
作者:
Nickolai Zeldovich
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
run rcu_gc in a separate proc, since it can sleep (in rcu_delayed bfree)
上级
d5fd5fdd
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
46 行增加
和
5 行删除
+46
-5
defs.h
defs.h
+1
-0
proc.c
proc.c
+18
-2
proc.h
proc.h
+1
-0
rcu.c
rcu.c
+26
-3
没有找到文件。
defs.h
浏览文件 @
982d0894
...
@@ -181,6 +181,7 @@ void rcu_end_read(void);
...
@@ -181,6 +181,7 @@ void rcu_end_read(void);
void
rcu_delayed
(
void
*
,
void
(
*
dofree
)(
void
*
));
void
rcu_delayed
(
void
*
,
void
(
*
dofree
)(
void
*
));
void
rcu_delayed2
(
int
,
uint
,
void
(
*
dofree
)(
int
,
uint
));
void
rcu_delayed2
(
int
,
uint
,
void
(
*
dofree
)(
int
,
uint
));
void
rcu_gc
(
void
);
void
rcu_gc
(
void
);
void
rcu_gc_worker
(
void
);
// swtch.S
// swtch.S
void
swtch
(
struct
context
**
,
struct
context
*
);
void
swtch
(
struct
context
**
,
struct
context
*
);
...
...
proc.c
浏览文件 @
982d0894
...
@@ -58,6 +58,7 @@ allocproc(void)
...
@@ -58,6 +58,7 @@ allocproc(void)
p
->
epoch
=
INF
;
p
->
epoch
=
INF
;
p
->
cpuid
=
cpu
->
id
;
p
->
cpuid
=
cpu
->
id
;
p
->
on_runq
=
-
1
;
p
->
on_runq
=
-
1
;
p
->
cpu_pin
=
0
;
snprintf
(
p
->
lockname
,
sizeof
(
p
->
lockname
),
"cv:proc:%d"
,
p
->
pid
);
snprintf
(
p
->
lockname
,
sizeof
(
p
->
lockname
),
"cv:proc:%d"
,
p
->
pid
);
initlock
(
&
p
->
lock
,
p
->
lockname
+
3
);
initlock
(
&
p
->
lock
,
p
->
lockname
+
3
);
...
@@ -162,6 +163,20 @@ userinit(void)
...
@@ -162,6 +163,20 @@ userinit(void)
addrun
(
p
);
addrun
(
p
);
p
->
state
=
RUNNABLE
;
p
->
state
=
RUNNABLE
;
release
(
&
p
->
lock
);
release
(
&
p
->
lock
);
for
(
uint
c
=
0
;
c
<
NCPU
;
c
++
)
{
struct
proc
*
rcup
=
allocproc
();
rcup
->
vmap
=
vmap_alloc
();
rcup
->
context
->
eip
=
(
uint
)
rcu_gc_worker
;
rcup
->
cwd
=
0
;
rcup
->
cpuid
=
c
;
rcup
->
cpu_pin
=
1
;
acquire
(
&
rcup
->
lock
);
rcup
->
state
=
RUNNABLE
;
addrun
(
rcup
);
release
(
&
rcup
->
lock
);
}
}
}
// Grow/shrink current process's memory by n bytes.
// Grow/shrink current process's memory by n bytes.
...
@@ -419,7 +434,7 @@ migrate(struct proc *p)
...
@@ -419,7 +434,7 @@ migrate(struct proc *p)
continue
;
continue
;
if
(
idle
[
c
])
{
// OK if there is a race
if
(
idle
[
c
])
{
// OK if there is a race
acquire
(
&
p
->
lock
);
acquire
(
&
p
->
lock
);
if
(
p
->
state
!=
RUNNABLE
)
{
if
(
p
->
state
!=
RUNNABLE
||
p
->
cpu_pin
)
{
release
(
&
p
->
lock
);
release
(
&
p
->
lock
);
continue
;
continue
;
}
}
...
@@ -450,7 +465,7 @@ steal_cb(void *vk, void *v, void *arg)
...
@@ -450,7 +465,7 @@ steal_cb(void *vk, void *v, void *arg)
struct
proc
*
p
=
v
;
struct
proc
*
p
=
v
;
acquire
(
&
p
->
lock
);
acquire
(
&
p
->
lock
);
if
(
p
->
state
!=
RUNNABLE
||
p
->
cpuid
==
cpu
->
id
)
{
if
(
p
->
state
!=
RUNNABLE
||
p
->
cpuid
==
cpu
->
id
||
p
->
cpu_pin
)
{
release
(
&
p
->
lock
);
release
(
&
p
->
lock
);
return
0
;
return
0
;
}
}
...
@@ -505,6 +520,7 @@ scheduler(void)
...
@@ -505,6 +520,7 @@ scheduler(void)
panic
(
"scheduler allocproc"
);
panic
(
"scheduler allocproc"
);
proc
=
schedp
;
proc
=
schedp
;
proc
->
cpu_pin
=
1
;
// Enabling mtrace calls in scheduler generates many mtrace_call_entrys.
// Enabling mtrace calls in scheduler generates many mtrace_call_entrys.
// mtrace_call_set(1, cpu->id);
// mtrace_call_set(1, cpu->id);
...
...
proc.h
浏览文件 @
982d0894
...
@@ -93,6 +93,7 @@ struct proc {
...
@@ -93,6 +93,7 @@ struct proc {
uint
rcu_read_depth
;
uint
rcu_read_depth
;
char
lockname
[
16
];
char
lockname
[
16
];
int
on_runq
;
int
on_runq
;
int
cpu_pin
;
};
};
// Process memory is laid out contiguously, low addresses first:
// Process memory is laid out contiguously, low addresses first:
...
...
rcu.c
浏览文件 @
982d0894
...
@@ -32,6 +32,7 @@ static struct { struct rcu_head x __attribute__((aligned (CACHELINE))); } rcu_q[
...
@@ -32,6 +32,7 @@ static struct { struct rcu_head x __attribute__((aligned (CACHELINE))); } rcu_q[
static
uint
global_epoch
__attribute__
((
aligned
(
CACHELINE
)));
static
uint
global_epoch
__attribute__
((
aligned
(
CACHELINE
)));
static
struct
{
struct
spinlock
l
__attribute__
((
aligned
(
CACHELINE
)));
}
rcu_lock
[
NCPU
];
static
struct
{
struct
spinlock
l
__attribute__
((
aligned
(
CACHELINE
)));
}
rcu_lock
[
NCPU
];
static
struct
{
int
v
__attribute__
((
aligned
(
CACHELINE
)));
}
delayed_nfree
[
NCPU
];
static
struct
{
int
v
__attribute__
((
aligned
(
CACHELINE
)));
}
delayed_nfree
[
NCPU
];
static
struct
{
struct
condvar
cv
__attribute__
((
aligned
(
CACHELINE
)));
}
rcu_cv
[
NCPU
];
enum
{
rcu_debug
=
0
};
enum
{
rcu_debug
=
0
};
...
@@ -41,6 +42,7 @@ rcuinit(void)
...
@@ -41,6 +42,7 @@ rcuinit(void)
for
(
int
i
=
0
;
i
<
NCPU
;
i
++
)
{
for
(
int
i
=
0
;
i
<
NCPU
;
i
++
)
{
initlock
(
&
rcu_lock
[
i
].
l
,
"rcu"
);
initlock
(
&
rcu_lock
[
i
].
l
,
"rcu"
);
TAILQ_INIT
(
&
rcu_q
[
i
].
x
);
TAILQ_INIT
(
&
rcu_q
[
i
].
x
);
initcondvar
(
&
rcu_cv
[
i
].
cv
,
"rcu_gc_cv"
);
}
}
}
}
...
@@ -63,7 +65,7 @@ rcu_min(void *vkey, void *v, void *arg){
...
@@ -63,7 +65,7 @@ rcu_min(void *vkey, void *v, void *arg){
// XXX use atomic instruction to update list (instead of holding lock)
// XXX use atomic instruction to update list (instead of holding lock)
// lists of lists?
// lists of lists?
void
void
rcu_gc
(
void
)
rcu_gc
_work
(
void
)
{
{
struct
rcu
*
r
,
*
nr
;
struct
rcu
*
r
,
*
nr
;
uint
min_epoch
=
global_epoch
;
uint
min_epoch
=
global_epoch
;
...
@@ -71,7 +73,7 @@ rcu_gc(void)
...
@@ -71,7 +73,7 @@ rcu_gc(void)
ns_enumerate
(
nspid
,
rcu_min
,
&
min_epoch
);
ns_enumerate
(
nspid
,
rcu_min
,
&
min_epoch
);
pushcli
();
// pushcli(); // not necessary: rcup->cpu_pin==1
acquire
(
&
rcu_lock
[
cpu
->
id
].
l
);
acquire
(
&
rcu_lock
[
cpu
->
id
].
l
);
for
(
r
=
TAILQ_FIRST
(
&
rcu_q
[
cpu
->
id
].
x
);
r
!=
NULL
;
r
=
nr
)
{
for
(
r
=
TAILQ_FIRST
(
&
rcu_q
[
cpu
->
id
].
x
);
r
!=
NULL
;
r
=
nr
)
{
...
@@ -102,12 +104,33 @@ rcu_gc(void)
...
@@ -102,12 +104,33 @@ rcu_gc(void)
if
(
rcu_debug
)
if
(
rcu_debug
)
cprintf
(
"rcu_gc: cpu %d n %d delayed_nfree=%d min_epoch=%d
\n
"
,
cprintf
(
"rcu_gc: cpu %d n %d delayed_nfree=%d min_epoch=%d
\n
"
,
cpu
->
id
,
n
,
delayed_nfree
[
cpu
->
id
],
min_epoch
);
cpu
->
id
,
n
,
delayed_nfree
[
cpu
->
id
],
min_epoch
);
popcli
();
// popcli(); // not necessary: rcup->cpu_pin==1
// global_epoch can be bumped anywhere; this seems as good a place as any
// global_epoch can be bumped anywhere; this seems as good a place as any
__sync_fetch_and_add
(
&
global_epoch
,
1
);
__sync_fetch_and_add
(
&
global_epoch
,
1
);
}
}
void
rcu_gc_worker
(
void
)
{
release
(
&
proc
->
lock
);
// initially held by scheduler
struct
spinlock
wl
;
initlock
(
&
wl
,
"rcu_gc_worker"
);
// dummy lock
acquire
(
&
wl
);
for
(;;)
{
rcu_gc_work
();
cv_sleep
(
&
rcu_cv
[
cpu
->
id
].
cv
,
&
wl
);
}
}
void
rcu_gc
(
void
)
{
cv_wakeup
(
&
rcu_cv
[
cpu
->
id
].
cv
);
}
// XXX Use atomic instruction to update list (instead of holding lock)
// XXX Use atomic instruction to update list (instead of holding lock)
static
void
static
void
rcu_delayed_int
(
struct
rcu
*
r
)
rcu_delayed_int
(
struct
rcu
*
r
)
...
...
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论