Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
00e57115
提交
00e57115
7月 12, 2009
创建
作者:
Russ Cox
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
more doc tweaks
上级
2c5f7aba
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
52 行增加
和
54 行删除
+52
-54
TRICKS
TRICKS
+13
-13
pipe.c
pipe.c
+20
-20
proc.c
proc.c
+18
-20
l-coordination.html
web/l-coordination.html
+1
-1
没有找到文件。
TRICKS
浏览文件 @
00e57115
...
@@ -4,6 +4,9 @@ might be worth pointing out in a longer explanation or in class.
...
@@ -4,6 +4,9 @@ might be worth pointing out in a longer explanation or in class.
---
---
[2009/07/12: No longer relevant; forkret1 changed
and this is now cleaner.]
forkret1 in trapasm.S is called with a tf argument.
forkret1 in trapasm.S is called with a tf argument.
In order to use it, forkret1 copies the tf pointer into
In order to use it, forkret1 copies the tf pointer into
%esp and then jumps to trapret, which pops the
%esp and then jumps to trapret, which pops the
...
@@ -45,21 +48,21 @@ always.
...
@@ -45,21 +48,21 @@ always.
There is a (harmless) race in pushcli, which does
There is a (harmless) race in pushcli, which does
eflags = read
_
eflags();
eflags = readeflags();
cli();
cli();
if(c
pus[cpu()].
ncli++ == 0)
if(c
->
ncli++ == 0)
c
pus[cpu()].
intena = eflags & FL_IF;
c
->
intena = eflags & FL_IF;
Consider a bottom-level pushcli.
Consider a bottom-level pushcli.
If interrupts are disabled already, then the right thing
If interrupts are disabled already, then the right thing
happens: read_eflags finds that FL_IF is not set,
happens: read_eflags finds that FL_IF is not set,
and intena =
1
. If interrupts are enabled, then
and intena =
0
. If interrupts are enabled, then
it is less clear that the right thing happens:
it is less clear that the right thing happens:
the read
_
eflags can execute, then the process
the readeflags can execute, then the process
can get preempted and rescheduled on another cpu,
can get preempted and rescheduled on another cpu,
and then once it starts running, perhaps with
and then once it starts running, perhaps with
interrupts disabled (can happen since the scheduler
interrupts disabled (can happen since the scheduler
only
dis
ables interrupts once per scheduling loop,
only
en
ables interrupts once per scheduling loop,
not every time it schedules a process), it will
not every time it schedules a process), it will
incorrectly record that interrupts *were* enabled.
incorrectly record that interrupts *were* enabled.
This doesn't matter, because if it was safe to be
This doesn't matter, because if it was safe to be
...
@@ -112,17 +115,13 @@ processors will need it.
...
@@ -112,17 +115,13 @@ processors will need it.
---
---
The code in
sys_
fork needs to read np->pid before
The code in fork needs to read np->pid before
setting np->state to RUNNABLE.
setting np->state to RUNNABLE.
int
int
sys_
fork(void)
fork(void)
{
{
int pid;
...
struct proc *np;
if((np = copyproc(cp)) == 0)
return -1;
pid = np->pid;
pid = np->pid;
np->state = RUNNABLE;
np->state = RUNNABLE;
return pid;
return pid;
...
@@ -134,3 +133,4 @@ get reused for a different process (with a new pid), all
...
@@ -134,3 +133,4 @@ get reused for a different process (with a new pid), all
before the return statement. So it's not safe to just do
before the return statement. So it's not safe to just do
"return np->pid;".
"return np->pid;".
This works because proc.h marks the pid as volatile.
pipe.c
浏览文件 @
00e57115
...
@@ -9,12 +9,12 @@
...
@@ -9,12 +9,12 @@
#define PIPESIZE 512
#define PIPESIZE 512
struct
pipe
{
struct
pipe
{
int
readopen
;
// read fd is still open
int
writeopen
;
// write fd is still open
uint
writep
;
// next index to write
uint
readp
;
// next index to read
struct
spinlock
lock
;
struct
spinlock
lock
;
char
data
[
PIPESIZE
];
char
data
[
PIPESIZE
];
uint
nread
;
// number of bytes read
uint
nwrite
;
// number of bytes written
int
readopen
;
// read fd is still open
int
writeopen
;
// write fd is still open
};
};
int
int
...
@@ -30,8 +30,8 @@ pipealloc(struct file **f0, struct file **f1)
...
@@ -30,8 +30,8 @@ pipealloc(struct file **f0, struct file **f1)
goto
bad
;
goto
bad
;
p
->
readopen
=
1
;
p
->
readopen
=
1
;
p
->
writeopen
=
1
;
p
->
writeopen
=
1
;
p
->
writep
=
0
;
p
->
nwrite
=
0
;
p
->
readp
=
0
;
p
->
nread
=
0
;
initlock
(
&
p
->
lock
,
"pipe"
);
initlock
(
&
p
->
lock
,
"pipe"
);
(
*
f0
)
->
type
=
FD_PIPE
;
(
*
f0
)
->
type
=
FD_PIPE
;
(
*
f0
)
->
readable
=
1
;
(
*
f0
)
->
readable
=
1
;
...
@@ -60,10 +60,10 @@ pipeclose(struct pipe *p, int writable)
...
@@ -60,10 +60,10 @@ pipeclose(struct pipe *p, int writable)
acquire
(
&
p
->
lock
);
acquire
(
&
p
->
lock
);
if
(
writable
){
if
(
writable
){
p
->
writeopen
=
0
;
p
->
writeopen
=
0
;
wakeup
(
&
p
->
readp
);
wakeup
(
&
p
->
nread
);
}
else
{
}
else
{
p
->
readopen
=
0
;
p
->
readopen
=
0
;
wakeup
(
&
p
->
writep
);
wakeup
(
&
p
->
nwrite
);
}
}
if
(
p
->
readopen
==
0
&&
p
->
writeopen
==
0
)
{
if
(
p
->
readopen
==
0
&&
p
->
writeopen
==
0
)
{
release
(
&
p
->
lock
);
release
(
&
p
->
lock
);
...
@@ -80,19 +80,19 @@ pipewrite(struct pipe *p, char *addr, int n)
...
@@ -80,19 +80,19 @@ pipewrite(struct pipe *p, char *addr, int n)
acquire
(
&
p
->
lock
);
acquire
(
&
p
->
lock
);
for
(
i
=
0
;
i
<
n
;
i
++
){
for
(
i
=
0
;
i
<
n
;
i
++
){
while
(
p
->
writep
==
p
->
readp
+
PIPESIZE
)
{
while
(
p
->
nwrite
==
p
->
nread
+
PIPESIZE
)
{
//DOC: pipewrite-full
if
(
p
->
readopen
==
0
||
cp
->
killed
){
if
(
p
->
readopen
==
0
||
cp
->
killed
){
release
(
&
p
->
lock
);
release
(
&
p
->
lock
);
return
-
1
;
return
-
1
;
}
}
wakeup
(
&
p
->
readp
);
wakeup
(
&
p
->
nread
);
sleep
(
&
p
->
writep
,
&
p
->
lock
);
sleep
(
&
p
->
nwrite
,
&
p
->
lock
);
//DOC: pipewrite-sleep
}
}
p
->
data
[
p
->
writep
++
%
PIPESIZE
]
=
addr
[
i
];
p
->
data
[
p
->
nwrite
++
%
PIPESIZE
]
=
addr
[
i
];
}
}
wakeup
(
&
p
->
readp
);
wakeup
(
&
p
->
nread
);
//DOC: pipewrite-wakeup1
release
(
&
p
->
lock
);
release
(
&
p
->
lock
);
return
i
;
return
n
;
}
}
int
int
...
@@ -101,19 +101,19 @@ piperead(struct pipe *p, char *addr, int n)
...
@@ -101,19 +101,19 @@ piperead(struct pipe *p, char *addr, int n)
int
i
;
int
i
;
acquire
(
&
p
->
lock
);
acquire
(
&
p
->
lock
);
while
(
p
->
readp
==
p
->
writep
&&
p
->
writeopen
){
while
(
p
->
nread
==
p
->
nwrite
&&
p
->
writeopen
){
//DOC: pipe-empty
if
(
cp
->
killed
){
if
(
cp
->
killed
){
release
(
&
p
->
lock
);
release
(
&
p
->
lock
);
return
-
1
;
return
-
1
;
}
}
sleep
(
&
p
->
readp
,
&
p
->
lock
);
sleep
(
&
p
->
nread
,
&
p
->
lock
);
//DOC: piperead-sleep
}
}
for
(
i
=
0
;
i
<
n
;
i
++
){
for
(
i
=
0
;
i
<
n
;
i
++
){
//DOC: piperead-copy
if
(
p
->
readp
==
p
->
writep
)
if
(
p
->
nread
==
p
->
nwrite
)
break
;
break
;
addr
[
i
]
=
p
->
data
[
p
->
readp
++
%
PIPESIZE
];
addr
[
i
]
=
p
->
data
[
p
->
nread
++
%
PIPESIZE
];
}
}
wakeup
(
&
p
->
writep
);
wakeup
(
&
p
->
nwrite
);
//DOC: piperead-wakeup
release
(
&
p
->
lock
);
release
(
&
p
->
lock
);
return
i
;
return
i
;
}
}
proc.c
浏览文件 @
00e57115
...
@@ -290,8 +290,8 @@ sleep(void *chan, struct spinlock *lk)
...
@@ -290,8 +290,8 @@ sleep(void *chan, struct spinlock *lk)
// guaranteed that we won't miss any wakeup
// guaranteed that we won't miss any wakeup
// (wakeup runs with ptable.lock locked),
// (wakeup runs with ptable.lock locked),
// so it's okay to release lk.
// so it's okay to release lk.
if
(
lk
!=
&
ptable
.
lock
){
if
(
lk
!=
&
ptable
.
lock
){
//DOC: sleeplock0
acquire
(
&
ptable
.
lock
);
acquire
(
&
ptable
.
lock
);
//DOC: sleeplock1
release
(
lk
);
release
(
lk
);
}
}
...
@@ -304,7 +304,7 @@ sleep(void *chan, struct spinlock *lk)
...
@@ -304,7 +304,7 @@ sleep(void *chan, struct spinlock *lk)
cp
->
chan
=
0
;
cp
->
chan
=
0
;
// Reacquire original lock.
// Reacquire original lock.
if
(
lk
!=
&
ptable
.
lock
){
if
(
lk
!=
&
ptable
.
lock
){
//DOC: sleeplock2
release
(
&
ptable
.
lock
);
release
(
&
ptable
.
lock
);
acquire
(
lk
);
acquire
(
lk
);
}
}
...
@@ -393,7 +393,6 @@ exit(void)
...
@@ -393,7 +393,6 @@ exit(void)
}
}
// Jump into the scheduler, never to return.
// Jump into the scheduler, never to return.
cp
->
killed
=
0
;
cp
->
state
=
ZOMBIE
;
cp
->
state
=
ZOMBIE
;
sched
();
sched
();
panic
(
"zombie exit"
);
panic
(
"zombie exit"
);
...
@@ -412,22 +411,21 @@ wait(void)
...
@@ -412,22 +411,21 @@ wait(void)
// Scan through table looking for zombie children.
// Scan through table looking for zombie children.
havekids
=
0
;
havekids
=
0
;
for
(
p
=
ptable
.
proc
;
p
<
&
ptable
.
proc
[
NPROC
];
p
++
){
for
(
p
=
ptable
.
proc
;
p
<
&
ptable
.
proc
[
NPROC
];
p
++
){
if
(
p
->
state
==
UNUSED
)
if
(
p
->
parent
!=
cp
)
continue
;
continue
;
if
(
p
->
parent
==
cp
){
havekids
=
1
;
havekids
=
1
;
if
(
p
->
state
==
ZOMBIE
){
if
(
p
->
state
==
ZOMBIE
){
// Found one.
// Found one.
pid
=
p
->
pid
;
kfree
(
p
->
mem
,
p
->
sz
);
kfree
(
p
->
mem
,
p
->
sz
);
kfree
(
p
->
kstack
,
KSTACKSIZE
);
kfree
(
p
->
kstack
,
KSTACKSIZE
);
pid
=
p
->
pid
;
p
->
state
=
UNUSED
;
p
->
state
=
UNUSED
;
p
->
pid
=
0
;
p
->
pid
=
0
;
p
->
parent
=
0
;
p
->
parent
=
0
;
p
->
name
[
0
]
=
0
;
p
->
name
[
0
]
=
0
;
p
->
killed
=
0
;
release
(
&
ptable
.
lock
);
release
(
&
ptable
.
lock
);
return
pid
;
return
pid
;
}
}
}
}
}
...
@@ -438,7 +436,7 @@ wait(void)
...
@@ -438,7 +436,7 @@ wait(void)
}
}
// Wait for children to exit. (See wakeup1 call in proc_exit.)
// Wait for children to exit. (See wakeup1 call in proc_exit.)
sleep
(
cp
,
&
ptable
.
lock
);
sleep
(
cp
,
&
ptable
.
lock
);
//DOC: wait-sleep
}
}
}
}
...
...
web/l-coordination.html
浏览文件 @
00e57115
...
@@ -47,7 +47,7 @@
...
@@ -47,7 +47,7 @@
<h3>
Sleep and wakeup - usage
</h3>
<h3>
Sleep and wakeup - usage
</h3>
Let's consider implementing a producer/consumer queue
Let's consider implementing a producer/consumer queue
(like a pipe) that can be used to hold a single non-null
char
pointer:
(like a pipe) that can be used to hold a single non-null pointer:
<pre>
<pre>
struct pcq {
struct pcq {
...
...
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论