Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
19333efb
提交
19333efb
5月 31, 2009
创建
作者:
rsc
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Some proc cleanup, moving some of copyproc into allocproc.
Also, an experiment: use "thread-local" storage for c and cp instead of the #define macro for curproc[cpu()].
上级
0c7f4838
显示空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
135 行增加
和
106 行删除
+135
-106
Makefile
Makefile
+4
-0
defs.h
defs.h
+9
-2
exec.c
exec.c
+1
-1
lapic.c
lapic.c
+1
-1
main.c
main.c
+14
-9
proc.c
proc.c
+73
-75
proc.h
proc.h
+23
-14
spinlock.c
spinlock.c
+4
-4
x86.h
x86.h
+6
-0
没有找到文件。
Makefile
浏览文件 @
19333efb
...
@@ -23,6 +23,7 @@ OBJS = \
...
@@ -23,6 +23,7 @@ OBJS = \
timer.o
\
timer.o
\
trapasm.o
\
trapasm.o
\
trap.o
\
trap.o
\
uart.o
\
vectors.o
\
vectors.o
\
# Cross-compiling (e.g., on Mac OS X)
# Cross-compiling (e.g., on Mac OS X)
...
@@ -139,6 +140,9 @@ bochs : fs.img xv6.img
...
@@ -139,6 +140,9 @@ bochs : fs.img xv6.img
qemu
:
fs.img xv6.img
qemu
:
fs.img xv6.img
qemu
-parallel
stdio
-hdb
fs.img xv6.img
qemu
-parallel
stdio
-hdb
fs.img xv6.img
qemutty
:
fs.img xv6.img
qemu
-nographic
-smp
2
-hdb
fs.img xv6.img
# CUT HERE
# CUT HERE
# prepare dist for students
# prepare dist for students
# after running make dist, probably want to
# after running make dist, probably want to
...
...
defs.h
浏览文件 @
19333efb
...
@@ -73,6 +73,7 @@ extern volatile uint* lapic;
...
@@ -73,6 +73,7 @@ extern volatile uint* lapic;
void
lapiceoi
(
void
);
void
lapiceoi
(
void
);
void
lapicinit
(
int
);
void
lapicinit
(
int
);
void
lapicstartap
(
uchar
,
uint
);
void
lapicstartap
(
uchar
,
uint
);
void
microdelay
(
int
);
// mp.c
// mp.c
extern
int
ismp
;
extern
int
ismp
;
...
@@ -92,14 +93,14 @@ int pipewrite(struct pipe*, char*, int);
...
@@ -92,14 +93,14 @@ int pipewrite(struct pipe*, char*, int);
// proc.c
// proc.c
struct
proc
*
copyproc
(
struct
proc
*
);
struct
proc
*
copyproc
(
struct
proc
*
);
struct
proc
*
curproc
(
void
);
void
exit
(
void
);
void
exit
(
void
);
int
growproc
(
int
);
int
growproc
(
int
);
int
kill
(
int
);
int
kill
(
int
);
void
pinit
(
void
);
void
pinit
(
void
);
void
procdump
(
void
);
void
procdump
(
void
);
void
scheduler
(
void
)
__attribute__
((
noreturn
));
void
scheduler
(
void
)
__attribute__
((
noreturn
));
void
setupsegs
(
struct
proc
*
);
void
ksegment
(
void
);
void
usegment
(
void
);
void
sleep
(
void
*
,
struct
spinlock
*
);
void
sleep
(
void
*
,
struct
spinlock
*
);
void
userinit
(
void
);
void
userinit
(
void
);
int
wait
(
void
);
int
wait
(
void
);
...
@@ -144,6 +145,12 @@ extern int ticks;
...
@@ -144,6 +145,12 @@ extern int ticks;
void
tvinit
(
void
);
void
tvinit
(
void
);
extern
struct
spinlock
tickslock
;
extern
struct
spinlock
tickslock
;
// uart.c
void
uartinit
(
void
);
void
uartintr
(
void
);
void
uartputc
(
int
);
// number of elements in fixed-size array
// number of elements in fixed-size array
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
exec.c
浏览文件 @
19333efb
...
@@ -104,7 +104,7 @@ exec(char *path, char **argv)
...
@@ -104,7 +104,7 @@ exec(char *path, char **argv)
cp
->
sz
=
sz
;
cp
->
sz
=
sz
;
cp
->
tf
->
eip
=
elf
.
entry
;
// main
cp
->
tf
->
eip
=
elf
.
entry
;
// main
cp
->
tf
->
esp
=
sp
;
cp
->
tf
->
esp
=
sp
;
setupsegs
(
cp
);
usegment
(
);
return
0
;
return
0
;
bad:
bad:
...
...
lapic.c
浏览文件 @
19333efb
...
@@ -121,7 +121,7 @@ lapiceoi(void)
...
@@ -121,7 +121,7 @@ lapiceoi(void)
// Spin for a given number of microseconds.
// Spin for a given number of microseconds.
// On real hardware would want to tune this dynamically.
// On real hardware would want to tune this dynamically.
static
void
void
microdelay
(
int
us
)
microdelay
(
int
us
)
{
{
volatile
int
j
=
0
;
volatile
int
j
=
0
;
...
...
main.c
浏览文件 @
19333efb
...
@@ -5,6 +5,9 @@
...
@@ -5,6 +5,9 @@
#include "proc.h"
#include "proc.h"
#include "x86.h"
#include "x86.h"
__thread
struct
cpu
*
c
;
__thread
struct
proc
*
cp
;
static
void
bootothers
(
void
);
static
void
bootothers
(
void
);
static
void
mpmain
(
void
)
__attribute__
((
noreturn
));
static
void
mpmain
(
void
)
__attribute__
((
noreturn
));
...
@@ -14,17 +17,19 @@ main(void)
...
@@ -14,17 +17,19 @@ main(void)
{
{
mpinit
();
// collect info about this machine
mpinit
();
// collect info about this machine
lapicinit
(
mpbcpu
());
lapicinit
(
mpbcpu
());
cprintf
(
"
\n
cpu%d: starting xv6
\n\n
"
,
cpu
());
ksegment
();
pinit
();
// process table
binit
();
// buffer cache
picinit
();
// interrupt controller
picinit
();
// interrupt controller
ioapicinit
();
// another interrupt controller
ioapicinit
();
// another interrupt controller
consoleinit
();
// I/O devices & their interrupts
uartinit
();
// serial port
cprintf
(
"
\n
cpu%d: starting xv6
\n\n
"
,
cpu
());
kinit
();
// physical memory allocator
kinit
();
// physical memory allocator
pinit
();
// process table
tvinit
();
// trap vectors
tvinit
();
// trap vectors
binit
();
// buffer cache
fileinit
();
// file table
fileinit
();
// file table
iinit
();
// inode cache
iinit
();
// inode cache
consoleinit
();
// I/O devices & their interrupts
ideinit
();
// disk
ideinit
();
// disk
if
(
!
ismp
)
if
(
!
ismp
)
timerinit
();
// uniprocessor timer
timerinit
();
// uniprocessor timer
...
@@ -40,12 +45,12 @@ main(void)
...
@@ -40,12 +45,12 @@ main(void)
static
void
static
void
mpmain
(
void
)
mpmain
(
void
)
{
{
cprintf
(
"cpu%d: mpmain
\n
"
,
cpu
());
idtinit
();
if
(
cpu
()
!=
mpbcpu
())
if
(
cpu
()
!=
mpbcpu
())
lapicinit
(
cpu
());
lapicinit
(
cpu
());
setupsegs
(
0
);
ksegment
();
xchg
(
&
cpus
[
cpu
()].
booted
,
1
);
cprintf
(
"cpu%d: mpmain
\n
"
,
cpu
());
idtinit
();
xchg
(
&
c
->
booted
,
1
);
cprintf
(
"cpu%d: scheduling
\n
"
,
cpu
());
cprintf
(
"cpu%d: scheduling
\n
"
,
cpu
());
scheduler
();
scheduler
();
...
...
proc.c
浏览文件 @
19333efb
...
@@ -36,16 +36,31 @@ allocproc(void)
...
@@ -36,16 +36,31 @@ allocproc(void)
if
(
p
->
state
==
UNUSED
){
if
(
p
->
state
==
UNUSED
){
p
->
state
=
EMBRYO
;
p
->
state
=
EMBRYO
;
p
->
pid
=
nextpid
++
;
p
->
pid
=
nextpid
++
;
release
(
&
proc_table_lock
);
goto
found
;
return
p
;
}
}
}
}
release
(
&
proc_table_lock
);
release
(
&
proc_table_lock
);
return
0
;
return
0
;
found:
release
(
&
proc_table_lock
);
// Allocate kernel stack if necessary.
if
((
p
->
kstack
=
kalloc
(
KSTACKSIZE
))
==
0
){
p
->
state
=
UNUSED
;
return
0
;
}
p
->
tf
=
(
struct
trapframe
*
)(
p
->
kstack
+
KSTACKSIZE
)
-
1
;
// Set up new context to start executing at forkret (see below).
p
->
context
=
(
struct
context
*
)
p
->
tf
-
1
;
memset
(
p
->
context
,
0
,
sizeof
(
*
p
->
context
));
p
->
context
->
eip
=
(
uint
)
forkret
;
return
p
;
}
}
// Grow current process's memory by n bytes.
// Grow current process's memory by n bytes.
// Return
old size
on success, -1 on failure.
// Return
0
on success, -1 on failure.
int
int
growproc
(
int
n
)
growproc
(
int
n
)
{
{
...
@@ -59,37 +74,53 @@ growproc(int n)
...
@@ -59,37 +74,53 @@ growproc(int n)
kfree
(
cp
->
mem
,
cp
->
sz
);
kfree
(
cp
->
mem
,
cp
->
sz
);
cp
->
mem
=
newmem
;
cp
->
mem
=
newmem
;
cp
->
sz
+=
n
;
cp
->
sz
+=
n
;
setupsegs
(
cp
);
usegment
(
);
return
cp
->
sz
-
n
;
return
0
;
}
}
// Set up CPU's segment descriptors and task state for a given process.
// Set up CPU's kernel segment descriptors.
// If p==0, set up for "idle" state for when scheduler() is running.
void
void
setupsegs
(
struct
proc
*
p
)
ksegment
(
void
)
{
{
struct
cpu
*
c
;
struct
cpu
*
c1
;
c1
=
&
cpus
[
cpu
()];
c1
->
gdt
[
0
]
=
SEG_NULL
;
c1
->
gdt
[
SEG_KCODE
]
=
SEG
(
STA_X
|
STA_R
,
0
,
0x100000
+
64
*
1024
-
1
,
0
);
c1
->
gdt
[
SEG_KDATA
]
=
SEG
(
STA_W
,
0
,
0xffffffff
,
0
);
c1
->
gdt
[
SEG_KCPU
]
=
SEG
(
STA_W
,
(
uint
)
&
c1
->
tls
+
sizeof
(
c1
->
tls
),
0xffffffff
,
0
);
c1
->
gdt
[
SEG_UCODE
]
=
SEG_NULL
;
c1
->
gdt
[
SEG_UDATA
]
=
SEG_NULL
;
c1
->
gdt
[
SEG_TSS
]
=
SEG_NULL
;
lgdt
(
c1
->
gdt
,
sizeof
(
c1
->
gdt
));
// Initialize cpu-local variables.
setgs
(
SEG_KCPU
<<
3
);
c
=
c1
;
cp
=
0
;
}
// Set up CPU's segment descriptors and task state for the current process.
// If cp==0, set up for "idle" state for when scheduler() is running.
void
usegment
(
void
)
{
pushcli
();
pushcli
();
c
=
&
cpus
[
cpu
()];
c
->
ts
.
ss0
=
SEG_KDATA
<<
3
;
c
->
ts
.
ss0
=
SEG_KDATA
<<
3
;
if
(
p
)
if
(
c
p
)
c
->
ts
.
esp0
=
(
uint
)(
p
->
kstack
+
KSTACKSIZE
);
c
->
ts
.
esp0
=
(
uint
)(
c
p
->
kstack
+
KSTACKSIZE
);
else
else
c
->
ts
.
esp0
=
0xffffffff
;
c
->
ts
.
esp0
=
0xffffffff
;
c
->
gdt
[
0
]
=
SEG_NULL
;
if
(
cp
){
c
->
gdt
[
SEG_KCODE
]
=
SEG
(
STA_X
|
STA_R
,
0
,
0x100000
+
64
*
1024
-
1
,
0
);
c
->
gdt
[
SEG_UCODE
]
=
SEG
(
STA_X
|
STA_R
,
(
uint
)
cp
->
mem
,
cp
->
sz
-
1
,
DPL_USER
);
c
->
gdt
[
SEG_KDATA
]
=
SEG
(
STA_W
,
0
,
0xffffffff
,
0
);
c
->
gdt
[
SEG_UDATA
]
=
SEG
(
STA_W
,
(
uint
)
cp
->
mem
,
cp
->
sz
-
1
,
DPL_USER
);
c
->
gdt
[
SEG_TSS
]
=
SEG16
(
STS_T32A
,
(
uint
)
&
c
->
ts
,
sizeof
(
c
->
ts
)
-
1
,
0
);
c
->
gdt
[
SEG_TSS
].
s
=
0
;
if
(
p
){
c
->
gdt
[
SEG_UCODE
]
=
SEG
(
STA_X
|
STA_R
,
(
uint
)
p
->
mem
,
p
->
sz
-
1
,
DPL_USER
);
c
->
gdt
[
SEG_UDATA
]
=
SEG
(
STA_W
,
(
uint
)
p
->
mem
,
p
->
sz
-
1
,
DPL_USER
);
}
else
{
}
else
{
c
->
gdt
[
SEG_UCODE
]
=
SEG_NULL
;
c
->
gdt
[
SEG_UCODE
]
=
SEG_NULL
;
c
->
gdt
[
SEG_UDATA
]
=
SEG_NULL
;
c
->
gdt
[
SEG_UDATA
]
=
SEG_NULL
;
}
}
c
->
gdt
[
SEG_TSS
]
=
SEG16
(
STS_T32A
,
(
uint
)
&
c
->
ts
,
sizeof
(
c
->
ts
)
-
1
,
0
);
c
->
gdt
[
SEG_TSS
].
s
=
0
;
lgdt
(
c
->
gdt
,
sizeof
(
c
->
gdt
));
lgdt
(
c
->
gdt
,
sizeof
(
c
->
gdt
));
ltr
(
SEG_TSS
<<
3
);
ltr
(
SEG_TSS
<<
3
);
...
@@ -109,40 +140,23 @@ copyproc(struct proc *p)
...
@@ -109,40 +140,23 @@ copyproc(struct proc *p)
if
((
np
=
allocproc
())
==
0
)
if
((
np
=
allocproc
())
==
0
)
return
0
;
return
0
;
// Allocate kernel stack.
// Copy process state from p.
if
((
np
->
kstack
=
kalloc
(
KSTACKSIZE
))
==
0
){
np
->
state
=
UNUSED
;
return
0
;
}
np
->
tf
=
(
struct
trapframe
*
)(
np
->
kstack
+
KSTACKSIZE
)
-
1
;
if
(
p
){
// Copy process state from p.
np
->
parent
=
p
;
memmove
(
np
->
tf
,
p
->
tf
,
sizeof
(
*
np
->
tf
));
np
->
sz
=
p
->
sz
;
np
->
sz
=
p
->
sz
;
if
((
np
->
mem
=
kalloc
(
np
->
sz
))
==
0
){
if
((
np
->
mem
=
kalloc
(
np
->
sz
))
==
0
){
kfree
(
np
->
kstack
,
KSTACKSIZE
);
kfree
(
np
->
kstack
,
KSTACKSIZE
);
np
->
kstack
=
0
;
np
->
kstack
=
0
;
np
->
state
=
UNUSED
;
np
->
state
=
UNUSED
;
np
->
parent
=
0
;
return
0
;
return
0
;
}
}
memmove
(
np
->
mem
,
p
->
mem
,
np
->
sz
);
memmove
(
np
->
mem
,
p
->
mem
,
np
->
sz
);
np
->
parent
=
p
;
*
np
->
tf
=
*
p
->
tf
;
for
(
i
=
0
;
i
<
NOFILE
;
i
++
)
for
(
i
=
0
;
i
<
NOFILE
;
i
++
)
if
(
p
->
ofile
[
i
])
if
(
p
->
ofile
[
i
])
np
->
ofile
[
i
]
=
filedup
(
p
->
ofile
[
i
]);
np
->
ofile
[
i
]
=
filedup
(
p
->
ofile
[
i
]);
np
->
cwd
=
idup
(
p
->
cwd
);
np
->
cwd
=
idup
(
p
->
cwd
);
}
// Set up new context to start executing at forkret (see below).
np
->
context
=
(
struct
context
*
)
np
->
tf
-
1
;
memset
(
np
->
context
,
0
,
sizeof
(
*
np
->
context
));
np
->
context
->
eip
=
(
uint
)
forkret
;
// Clear %eax so that fork system call returns 0 in child.
np
->
tf
->
eax
=
0
;
return
np
;
return
np
;
}
}
...
@@ -153,10 +167,14 @@ userinit(void)
...
@@ -153,10 +167,14 @@ userinit(void)
struct
proc
*
p
;
struct
proc
*
p
;
extern
uchar
_binary_initcode_start
[],
_binary_initcode_size
[];
extern
uchar
_binary_initcode_start
[],
_binary_initcode_size
[];
p
=
copyproc
(
0
);
p
=
allocproc
();
initproc
=
p
;
// Initialize memory from initcode.S
p
->
sz
=
PAGE
;
p
->
sz
=
PAGE
;
p
->
mem
=
kalloc
(
p
->
sz
);
p
->
mem
=
kalloc
(
p
->
sz
);
p
->
cwd
=
namei
(
"/"
);
memmove
(
p
->
mem
,
_binary_initcode_start
,
(
int
)
_binary_initcode_size
);
memset
(
p
->
tf
,
0
,
sizeof
(
*
p
->
tf
));
memset
(
p
->
tf
,
0
,
sizeof
(
*
p
->
tf
));
p
->
tf
->
cs
=
(
SEG_UCODE
<<
3
)
|
DPL_USER
;
p
->
tf
->
cs
=
(
SEG_UCODE
<<
3
)
|
DPL_USER
;
p
->
tf
->
ds
=
(
SEG_UDATA
<<
3
)
|
DPL_USER
;
p
->
tf
->
ds
=
(
SEG_UDATA
<<
3
)
|
DPL_USER
;
...
@@ -164,30 +182,12 @@ userinit(void)
...
@@ -164,30 +182,12 @@ userinit(void)
p
->
tf
->
ss
=
p
->
tf
->
ds
;
p
->
tf
->
ss
=
p
->
tf
->
ds
;
p
->
tf
->
eflags
=
FL_IF
;
p
->
tf
->
eflags
=
FL_IF
;
p
->
tf
->
esp
=
p
->
sz
;
p
->
tf
->
esp
=
p
->
sz
;
p
->
tf
->
eip
=
0
;
// beginning of initcode.S
// Make return address readable; needed for some gcc.
p
->
tf
->
esp
-=
4
;
*
(
uint
*
)(
p
->
mem
+
p
->
tf
->
esp
)
=
0xefefefef
;
// On entry to user space, start executing at beginning of initcode.S.
p
->
tf
->
eip
=
0
;
memmove
(
p
->
mem
,
_binary_initcode_start
,
(
int
)
_binary_initcode_size
);
safestrcpy
(
p
->
name
,
"initcode"
,
sizeof
(
p
->
name
));
safestrcpy
(
p
->
name
,
"initcode"
,
sizeof
(
p
->
name
));
p
->
state
=
RUNNABLE
;
p
->
cwd
=
namei
(
"/"
);
initproc
=
p
;
}
// Return currently running process.
struct
proc
*
curproc
(
void
)
{
struct
proc
*
p
;
pushcli
();
p
->
state
=
RUNNABLE
;
p
=
cpus
[
cpu
()].
curproc
;
popcli
();
return
p
;
}
}
//PAGEBREAK: 42
//PAGEBREAK: 42
...
@@ -202,10 +202,8 @@ void
...
@@ -202,10 +202,8 @@ void
scheduler
(
void
)
scheduler
(
void
)
{
{
struct
proc
*
p
;
struct
proc
*
p
;
struct
cpu
*
c
;
int
i
;
int
i
;
c
=
&
cpus
[
cpu
()];
for
(;;){
for
(;;){
// Enable interrupts on this processor, in lieu of saving intena.
// Enable interrupts on this processor, in lieu of saving intena.
sti
();
sti
();
...
@@ -220,15 +218,15 @@ scheduler(void)
...
@@ -220,15 +218,15 @@ scheduler(void)
// Switch to chosen process. It is the process's job
// Switch to chosen process. It is the process's job
// to release proc_table_lock and then reacquire it
// to release proc_table_lock and then reacquire it
// before jumping back to us.
// before jumping back to us.
c
->
curproc
=
p
;
c
p
=
p
;
setupsegs
(
p
);
usegment
(
);
p
->
state
=
RUNNING
;
p
->
state
=
RUNNING
;
swtch
(
&
c
->
context
,
&
p
->
context
);
swtch
(
&
c
->
context
,
&
p
->
context
);
// Process is done running for now.
// Process is done running for now.
// It should have changed its p->state before coming back.
// It should have changed its p->state before coming back.
c
->
curproc
=
0
;
c
p
=
0
;
setupsegs
(
0
);
usegment
(
);
}
}
release
(
&
proc_table_lock
);
release
(
&
proc_table_lock
);
...
@@ -236,7 +234,7 @@ scheduler(void)
...
@@ -236,7 +234,7 @@ scheduler(void)
}
}
// Enter scheduler. Must already hold proc_table_lock
// Enter scheduler. Must already hold proc_table_lock
// and have changed c
urproc[cpu()]
->state.
// and have changed c
p
->state.
void
void
sched
(
void
)
sched
(
void
)
{
{
...
@@ -248,12 +246,12 @@ sched(void)
...
@@ -248,12 +246,12 @@ sched(void)
panic
(
"sched running"
);
panic
(
"sched running"
);
if
(
!
holding
(
&
proc_table_lock
))
if
(
!
holding
(
&
proc_table_lock
))
panic
(
"sched proc_table_lock"
);
panic
(
"sched proc_table_lock"
);
if
(
c
pus
[
cpu
()].
ncli
!=
1
)
if
(
c
->
ncli
!=
1
)
panic
(
"sched locks"
);
panic
(
"sched locks"
);
intena
=
c
pus
[
cpu
()].
intena
;
intena
=
c
->
intena
;
swtch
(
&
cp
->
context
,
&
c
pus
[
cpu
()].
context
);
swtch
(
&
cp
->
context
,
&
c
->
context
);
c
pus
[
cpu
()].
intena
=
intena
;
c
->
intena
=
intena
;
}
}
// Give up the CPU for one scheduling round.
// Give up the CPU for one scheduling round.
...
@@ -421,6 +419,7 @@ wait(void)
...
@@ -421,6 +419,7 @@ wait(void)
if
(
p
->
state
==
UNUSED
)
if
(
p
->
state
==
UNUSED
)
continue
;
continue
;
if
(
p
->
parent
==
cp
){
if
(
p
->
parent
==
cp
){
havekids
=
1
;
if
(
p
->
state
==
ZOMBIE
){
if
(
p
->
state
==
ZOMBIE
){
// Found one.
// Found one.
kfree
(
p
->
mem
,
p
->
sz
);
kfree
(
p
->
mem
,
p
->
sz
);
...
@@ -433,7 +432,6 @@ wait(void)
...
@@ -433,7 +432,6 @@ wait(void)
release
(
&
proc_table_lock
);
release
(
&
proc_table_lock
);
return
pid
;
return
pid
;
}
}
havekids
=
1
;
}
}
}
}
...
...
proc.h
浏览文件 @
19333efb
// Segments in proc->gdt
// Segments in proc->gdt.
// Also known to bootasm.S and trapasm.S
#define SEG_KCODE 1 // kernel code
#define SEG_KCODE 1 // kernel code
#define SEG_KDATA 2 // kernel data+stack
#define SEG_KDATA 2 // kernel data+stack
#define SEG_UCODE 3
#define SEG_KCPU 3 // kernel per-cpu data
#define SEG_UDATA 4
#define SEG_UCODE 4
#define SEG_TSS 5 // this process's task state
#define SEG_UDATA 5
#define NSEGS 6
#define SEG_TSS 6 // this process's task state
#define NSEGS 7
// Saved registers for kernel context switches.
// Saved registers for kernel context switches.
// Don't need to save all the segment registers (%cs, etc),
// Don't need to save all the segment registers (%cs, etc),
// because they are constant across kernel contexts.
// because they are constant across kernel contexts.
// Stack pointer is encoded in the address of context,
// Don't need to save %eax, %ecx, %edx, because the
// which must be placed at the bottom of the stack.
// x86 convention is that the caller has saved them.
// The layout of context must match code in swtch.S.
// Contexts are stored at the bottom of the stack they
// describe; the stack pointer is the address of the context.
// The layout of the context must match the code in swtch.S.
struct
context
{
struct
context
{
uint
edi
;
uint
edi
;
uint
esi
;
uint
esi
;
...
@@ -30,12 +34,12 @@ struct proc {
...
@@ -30,12 +34,12 @@ struct proc {
enum
proc_state
state
;
// Process state
enum
proc_state
state
;
// Process state
int
pid
;
// Process ID
int
pid
;
// Process ID
struct
proc
*
parent
;
// Parent process
struct
proc
*
parent
;
// Parent process
struct
trapframe
*
tf
;
// Trap frame for current syscall
struct
context
*
context
;
// Switch here to run process
void
*
chan
;
// If non-zero, sleeping on chan
void
*
chan
;
// If non-zero, sleeping on chan
int
killed
;
// If non-zero, have been killed
int
killed
;
// If non-zero, have been killed
struct
file
*
ofile
[
NOFILE
];
// Open files
struct
file
*
ofile
[
NOFILE
];
// Open files
struct
inode
*
cwd
;
// Current directory
struct
inode
*
cwd
;
// Current directory
struct
context
*
context
;
// Switch here to run process
struct
trapframe
*
tf
;
// Trap frame for current syscall
char
name
[
16
];
// Process name (debugging)
char
name
[
16
];
// Process name (debugging)
};
};
...
@@ -48,18 +52,23 @@ struct proc {
...
@@ -48,18 +52,23 @@ struct proc {
// Per-CPU state
// Per-CPU state
struct
cpu
{
struct
cpu
{
uchar
apicid
;
// Local APIC ID
uchar
apicid
;
// Local APIC ID
struct
proc
*
curproc
;
// Process currently running.
struct
context
*
context
;
// Switch here to enter scheduler
struct
context
*
context
;
// Switch here to enter scheduler
struct
taskstate
ts
;
// Used by x86 to find stack for interrupt
struct
taskstate
ts
;
// Used by x86 to find stack for interrupt
struct
segdesc
gdt
[
NSEGS
];
// x86 global descriptor table
struct
segdesc
gdt
[
NSEGS
];
// x86 global descriptor table
volatile
uint
booted
;
// Has the CPU started?
volatile
uint
booted
;
// Has the CPU started?
int
ncli
;
// Depth of pushcli nesting.
int
ncli
;
// Depth of pushcli nesting.
int
intena
;
// Were interrupts enabled before pushcli?
int
intena
;
// Were interrupts enabled before pushcli?
void
*
tls
[
2
];
};
};
extern
struct
cpu
cpus
[
NCPU
];
extern
struct
cpu
cpus
[
NCPU
];
extern
int
ncpu
;
extern
int
ncpu
;
// "cp" is a short alias for curproc().
// Per-CPU variables, holding pointers to the
// It gets used enough to make this worthwhile.
// current cpu and to the current process.
#define cp curproc()
// The __thread prefix tells gcc to refer to them in the segment
// pointed at by gs; the name __thread derives from the use
// of the same mechanism to provide per-thread storage in
// multithreaded user programs.
extern
__thread
struct
cpu
*
c
;
// This cpu.
extern
__thread
struct
proc
*
cp
;
// Current process on this cpu.
spinlock.c
浏览文件 @
19333efb
...
@@ -102,8 +102,8 @@ pushcli(void)
...
@@ -102,8 +102,8 @@ pushcli(void)
eflags
=
readeflags
();
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
;
}
}
void
void
...
@@ -111,9 +111,9 @@ popcli(void)
...
@@ -111,9 +111,9 @@ popcli(void)
{
{
if
(
readeflags
()
&
FL_IF
)
if
(
readeflags
()
&
FL_IF
)
panic
(
"popcli - interruptible"
);
panic
(
"popcli - interruptible"
);
if
(
--
c
pus
[
cpu
()].
ncli
<
0
)
if
(
--
c
->
ncli
<
0
)
panic
(
"popcli"
);
panic
(
"popcli"
);
if
(
c
pus
[
cpu
()].
ncli
==
0
&&
cpus
[
cpu
()].
intena
)
if
(
c
->
ncli
==
0
&&
c
->
intena
)
sti
();
sti
();
}
}
x86.h
浏览文件 @
19333efb
...
@@ -104,6 +104,12 @@ xchg(volatile uint *addr, uint newval)
...
@@ -104,6 +104,12 @@ xchg(volatile uint *addr, uint newval)
}
}
static
inline
void
static
inline
void
setgs
(
ushort
gs
)
{
asm
volatile
(
"movw %0, %%gs"
:
:
"r"
(
gs
));
}
static
inline
void
cli
(
void
)
cli
(
void
)
{
{
asm
volatile
(
"cli"
);
asm
volatile
(
"cli"
);
...
...
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论