Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
00019b41
提交
00019b41
3月 09, 2012
创建
作者:
Robert Morris
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
dependency-aware shell
上级
b081cfec
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
205 行增加
和
28 行删除
+205
-28
wqsh.cc
bin/wqsh.cc
+205
-28
没有找到文件。
bin/wqsh.cc
浏览文件 @
00019b41
//
// A simple shell that uses a dependency-aware layer on
// top of wq to schedule commands.
//
// If you give this script to wqsh:
// cp README x
// cp x y
// cp README z
// It will ask wq to run the two "cp README ..." commands in parallel,
// but will block the "cp x y" until the first cp has completed.
//
#include "types.h"
#include "types.h"
#include "user.h"
#include "user.h"
#include "fcntl.h"
#include "fcntl.h"
#include "wq.hh"
#include "wq.hh"
//
// Adapt wq to understand simple dependencies
//
class
dwork
;
class
dwq
{
private
:
static
const
int
max
=
100
;
// keep track of sequence of push()ed dworks.
// so we know which are done, and thus what
// dependencies are or are not satisfied.
int
n
;
dwork
*
da
[
max
];
// is it OK to run da[i]?
int
can_run
(
int
i
);
public
:
static
void
*
operator
new
(
unsigned
long
n
){
return
malloc
(
n
);
}
dwq
()
{
n
=
0
;
}
int
done
();
void
push
(
dwork
*
);
void
run
();
};
class
dwork
{
private
:
friend
class
dwq
;
cwork
*
w
;
int
started
;
int
done
;
static
const
int
max
=
10
;
int
nneeds
,
nsatisfies
;
int
_needs
[
max
];
int
_satisfies
[
max
];
static
void
gogo
(
void
*
a0
,
void
*
a1
,
void
*
a2
);
public
:
static
void
*
operator
new
(
unsigned
long
n
){
return
malloc
(
n
);
}
dwork
(
void
*
fn
,
void
*
arg
);
void
needs
(
int
);
// must wait for this dependency, for input
void
satisfies
(
int
);
// output satisfies this dependency
};
void
dwq
::
push
(
dwork
*
dw
)
{
assert
(
n
+
1
<
max
);
da
[
n
++
]
=
dw
;
}
int
dwq
::
done
()
{
int
ndone
=
0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
)
if
(
da
[
i
]
->
done
)
ndone
++
;
return
ndone
>=
n
;
}
int
dwq
::
can_run
(
int
di
)
{
dwork
*
w
=
da
[
di
];
int
ready
[
dwork
::
max
];
// by default, all symbolic resources are ready.
for
(
int
i
=
0
;
i
<
w
->
nneeds
;
i
++
)
ready
[
i
]
=
1
;
// for each input w needs, figure out if the most
// recent provider is done.
for
(
int
i
=
0
;
i
<
di
;
i
++
){
for
(
int
j
=
0
;
j
<
w
->
nneeds
;
j
++
){
for
(
int
k
=
0
;
k
<
da
[
i
]
->
nsatisfies
;
k
++
){
if
(
w
->
_needs
[
j
]
==
da
[
i
]
->
_satisfies
[
k
]){
ready
[
j
]
=
da
[
i
]
->
done
;
}
}
}
}
// are all inputs ready?
for
(
int
i
=
0
;
i
<
w
->
nneeds
;
i
++
){
if
(
ready
[
i
]
==
0
){
printf
(
"can_run(%d) 0
\n
"
,
di
);
return
0
;
}
}
printf
(
"can_run(%d) 1
\n
"
,
di
);
return
1
;
}
// find dworks w/ satisfied inputs, run them, see
// if they un-block further dworks, &c.
void
dwq
::
run
()
{
while
(
done
()
==
0
){
for
(
int
i
=
0
;
i
<
n
;
i
++
){
if
(
da
[
i
]
->
done
==
0
&&
da
[
i
]
->
started
==
0
&&
can_run
(
i
)){
da
[
i
]
->
started
=
1
;
wq_push
(
da
[
i
]
->
w
);
}
}
wq_trywork
();
}
}
void
dwork
::
gogo
(
void
*
a0
,
void
*
a1
,
void
*
a2
)
{
dwork
*
w
=
(
dwork
*
)
a0
;
auto
fn
=
(
void
(
*
)(
void
*
))
a1
;
fn
(
a2
);
w
->
done
=
1
;
}
dwork
::
dwork
(
void
*
fn
,
void
*
arg
)
{
w
=
new
cwork
();
w
->
rip
=
(
void
*
)
dwork
::
gogo
;
w
->
arg0
=
this
;
w
->
arg1
=
fn
;
w
->
arg2
=
arg
;
started
=
0
;
done
=
0
;
nneeds
=
0
;
nsatisfies
=
0
;
}
// this dwork must wait for some previously pushed
// dwork to generate output with symbolic name x.
void
dwork
::
needs
(
int
x
)
{
assert
(
nneeds
<
max
);
_needs
[
nneeds
++
]
=
x
;
}
// this dwork generates output with symbolic name x,
// so any dwork needing (waiting for) x can start.
void
dwork
::
satisfies
(
int
x
)
{
assert
(
nsatisfies
<
max
);
_satisfies
[
nsatisfies
++
]
=
x
;
}
//
// parse shell scripts
//
class
thing
{
class
thing
{
protected
:
protected
:
int
done
;
int
done
;
...
@@ -16,7 +187,7 @@ public:
...
@@ -16,7 +187,7 @@ public:
thing
()
{
done
=
0
;
}
thing
()
{
done
=
0
;
}
virtual
~
thing
();
virtual
~
thing
();
virtual
void
print
()
=
0
;
virtual
void
print
()
=
0
;
virtual
void
run
()
=
0
;
virtual
void
run
(
dwq
*
)
=
0
;
int
checkdone
()
{
return
done
;
}
int
checkdone
()
{
return
done
;
}
};
};
...
@@ -28,7 +199,8 @@ public:
...
@@ -28,7 +199,8 @@ public:
cmd
()
{
argc
=
0
;
}
cmd
()
{
argc
=
0
;
}
void
print
();
void
print
();
void
run
();
void
run
(
dwq
*
);
void
reallyrun
();
static
cmd
*
parse
();
static
cmd
*
parse
();
};
};
...
@@ -40,7 +212,7 @@ public:
...
@@ -40,7 +212,7 @@ public:
sequence
()
{
n
=
0
;
}
sequence
()
{
n
=
0
;
}
void
print
();
void
print
();
void
run
();
void
run
(
dwq
*
);
static
sequence
*
parse
();
static
sequence
*
parse
();
};
};
...
@@ -83,7 +255,14 @@ cmd::parse()
...
@@ -83,7 +255,14 @@ cmd::parse()
}
}
void
void
cmd
::
run
()
blah
(
void
*
x
)
{
cmd
*
c
=
(
cmd
*
)
x
;
c
->
reallyrun
();
}
void
cmd
::
reallyrun
()
{
{
int
pid
=
fork
(
0
);
int
pid
=
fork
(
0
);
if
(
pid
<
0
){
if
(
pid
<
0
){
...
@@ -102,6 +281,23 @@ cmd::run()
...
@@ -102,6 +281,23 @@ cmd::run()
}
}
void
void
cmd
::
run
(
dwq
*
d
)
{
dwork
*
w
=
new
dwork
((
void
*
)
blah
,
this
);
if
(
argc
==
3
&&
strcmp
(
argv
[
0
],
"cp"
)
==
0
){
// this isn't correct; it's pessimistic in that
// distinct files can be mapped to the same "need" key,
// and that if you use different names for the same
// file, we won't realize they are the same.
w
->
needs
(
argv
[
1
][
0
]);
w
->
satisfies
(
argv
[
2
][
0
]);
}
else
{
printf
(
"warning: don't understand %s dependencies
\n
"
,
argv
[
0
]);
}
d
->
push
(
w
);
}
void
cmd
::
print
()
cmd
::
print
()
{
{
for
(
int
i
=
0
;
i
<
argc
;
i
++
)
for
(
int
i
=
0
;
i
<
argc
;
i
++
)
...
@@ -123,31 +319,10 @@ sequence::parse()
...
@@ -123,31 +319,10 @@ sequence::parse()
}
}
void
void
blah
(
void
*
x
)
sequence
::
run
(
dwq
*
d
)
{
thing
*
t
=
(
thing
*
)
x
;
t
->
run
();
}
void
sequence
::
run
()
{
{
for
(
int
i
=
0
;
i
<
n
;
i
++
){
for
(
int
i
=
0
;
i
<
n
;
i
++
){
cwork
*
w
=
new
cwork
();
a
[
i
]
->
run
(
d
);
w
->
rip
=
(
void
*
)
blah
;
w
->
arg0
=
a
[
i
];
wq_push
(
w
);
}
while
(
1
){
int
do_more
=
0
;
for
(
int
i
=
0
;
i
<
n
;
i
++
){
if
(
a
[
i
]
->
checkdone
()
==
0
){
do_more
+=
1
;
}
}
if
(
do_more
==
0
)
break
;
wq_trywork
();
}
}
done
=
1
;
done
=
1
;
}
}
...
@@ -163,8 +338,10 @@ int
...
@@ -163,8 +338,10 @@ int
main
(
void
)
main
(
void
)
{
{
initwq
();
initwq
();
dwq
*
d
=
new
dwq
();
sequence
*
s
=
sequence
::
parse
();
sequence
*
s
=
sequence
::
parse
();
if
(
s
){
if
(
s
){
s
->
run
();
s
->
run
(
d
);
d
->
run
();
}
}
}
}
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论