提交 65bd8e13 创建 作者: rsc's avatar rsc

New scheduler.

Removed cli and sti stack in favor of tracking number of locks held on each CPU and explicit conditionals in spinlock.c.
上级 40a2a083
......@@ -113,7 +113,7 @@ void
cprintf(char *fmt, ...)
{
int i, state = 0, c;
unsigned int *ap = (unsigned int *) &fmt + 1;
unsigned int *ap = (unsigned int *)(void*)&fmt + 1;
if(use_console_lock)
acquire(&console_lock);
......
......@@ -13,7 +13,6 @@ struct proc;
struct jmpbuf;
void setupsegs(struct proc *);
struct proc * newproc(void);
void swtch(int);
struct spinlock;
void sleep(void *, struct spinlock *);
void wakeup(void *);
......@@ -22,8 +21,6 @@ void proc_exit(void);
int proc_kill(int);
int proc_wait(void);
void yield(void);
void cli(void);
void sti(void);
// swtch.S
struct jmpbuf;
......
......@@ -107,7 +107,7 @@ romimage: file=$BXSHARE/BIOS-bochs-latest, address=0xf0000
# 650Mhz Athlon K-7 with Linux 2.4.4/egcs-2.91.66 2 to 2.5 Mips
# 400Mhz Pentium II with Linux 2.0.36/egcs-1.0.3 1 to 1.8 Mips
#=======================================================================
cpu: count=2, ips=10000000
cpu: count=2, ips=10000000, reset_on_triple_fault=0
#=======================================================================
# MEGS
......
......@@ -18,19 +18,19 @@ extern uint8_t _binary_userfs_start[], _binary_userfs_size[];
extern int use_console_lock;
struct spinlock sillylock; // hold this to keep interrupts disabled
int
main()
{
struct proc *p;
if (acpu) {
cpus[cpu()].clis = 1;
cprintf("an application processor\n");
idtinit(); // CPU's idt
lapic_init(cpu());
lapic_timerinit();
lapic_enableintr();
sti();
scheduler();
}
acpu = 1;
......@@ -40,10 +40,9 @@ main()
mp_init(); // collect info about this machine
acquire(&sillylock);
use_console_lock = 1;
cpus[cpu()].clis = 1; // cpu starts as if we had called cli()
lapic_init(mp_bcpu());
cprintf("\nxV6\n\n");
......@@ -56,7 +55,7 @@ main()
// create fake process zero
p = &proc[0];
memset(p, 0, sizeof *p);
p->state = WAITING;
p->state = SLEEPING;
p->sz = 4 * PAGE;
p->mem = kalloc(p->sz);
memset(p->mem, 0, p->sz);
......@@ -88,6 +87,7 @@ main()
//load_icode(p, _binary_userfs_start, (unsigned) _binary_userfs_size);
p->state = RUNNABLE;
cprintf("loaded userfs\n");
release(&sillylock);
scheduler();
......
差异被折叠。
......@@ -33,7 +33,7 @@ struct jmpbuf {
int jb_eip;
};
enum proc_state { UNUSED, EMBRYO, WAITING, RUNNABLE, RUNNING, ZOMBIE };
enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
struct proc{
char *mem; // start of process's physical memory
......@@ -46,7 +46,6 @@ struct proc{
int ppid;
void *chan; // sleep
int killed;
int locks; // # of locks currently held
struct fd *fds[NOFILE];
struct Taskstate ts; // only to give cpu address of kernel stack
......@@ -71,7 +70,7 @@ struct cpu {
struct jmpbuf jmpbuf;
char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main()
struct proc *lastproc; // last proc scheduled on this cpu (never NULL)
int clis; // cli() nesting depth
int nlock; // # of locks currently held
};
extern struct cpu cpus[NCPU];
......
......@@ -6,53 +6,47 @@
#include "proc.h"
#include "spinlock.h"
#define DEBUG 0
// Can't call cprintf from inside these routines,
// because cprintf uses them itself.
#define cprintf dont_use_cprintf
extern int use_console_lock;
int getcallerpc(void *v) {
return ((int*)v)[-1];
int
getcallerpc(void *v)
{
return ((int*)v)[-1];
}
void
acquire1(struct spinlock * lock, struct proc *cp)
{
if(DEBUG) cprintf("cpu%d: acquiring at %x\n", cpu(), getcallerpc(&lock));
cli();
while ( cmpxchg(0, 1, &lock->locked) == 1 ) { ; }
lock->locker_pc = getcallerpc(&lock);
if(cp)
cp->locks += 1;
if(DEBUG) cprintf("cpu%d: acquired at %x\n", cpu(), getcallerpc(&lock));
if(cpus[cpu()].nlock++ == 0)
cli();
while(cmpxchg(0, 1, &lock->locked) == 1)
;
cpuid(0, 0, 0, 0, 0); // memory barrier
lock->locker_pc = getcallerpc(&lock);
}
void
release1(struct spinlock * lock, struct proc *cp)
{
if(DEBUG) cprintf ("cpu%d: releasing at %x\n", cpu(), getcallerpc(&lock));
if(lock->locked != 1)
panic("release");
if(cp)
cp->locks -= 1;
cmpxchg(1, 0, &lock->locked);
sti();
cpuid(0, 0, 0, 0, 0); // memory barrier
lock->locked = 0;
if(--cpus[cpu()].nlock == 0)
sti();
}
void
acquire(struct spinlock *lock)
{
acquire1(lock, curproc[cpu()]);
acquire1(lock, curproc[cpu()]);
}
void
release(struct spinlock *lock)
{
release1(lock, curproc[cpu()]);
release1(lock, curproc[cpu()]);
}
......@@ -34,8 +34,9 @@ fetchint(struct proc *p, unsigned addr, int *ip)
return 0;
}
// This arg is void* so that both int* and uint* can be passed.
int
fetcharg(int argno, int *ip)
fetcharg(int argno, void *ip)
{
unsigned esp;
......
......@@ -36,11 +36,6 @@ trap(struct Trapframe *tf)
{
int v = tf->tf_trapno;
if(cpus[cpu()].clis){
cprintf("cpu %d v %d eip %x\n", cpu(), v, tf->tf_eip);
panic("interrupt while interrupts are off");
}
if(v == T_SYSCALL){
struct proc *cp = curproc[cpu()];
int num = cp->tf->tf_regs.reg_eax;
......@@ -56,12 +51,10 @@ trap(struct Trapframe *tf)
panic("trap ret but not RUNNING");
if(tf != cp->tf)
panic("trap ret wrong tf");
if(cp->locks){
if(cpus[cpu()].nlock){
cprintf("num=%d\n", num);
panic("syscall returning locks held");
}
if(cpus[cpu()].clis)
panic("syscall returning but clis != 0");
if((read_eflags() & FL_IF) == 0)
panic("syscall returning but FL_IF clear");
if(read_esp() < (unsigned)cp->kstack ||
......@@ -75,7 +68,7 @@ trap(struct Trapframe *tf)
if(v == (IRQ_OFFSET + IRQ_TIMER)){
struct proc *cp = curproc[cpu()];
lapic_timerintr();
if(cp && cp->locks)
if(cpus[cpu()].nlock)
panic("timer interrupt while holding a lock");
if(cp){
#if 1
......
#include "mmu.h"
.text
.globl alltraps
.globl trap
.globl trap
.globl trapret1
.globl alltraps
alltraps:
/* vectors.S sends all traps here */
pushl %ds # build
......@@ -16,11 +18,11 @@ alltraps:
addl $4, %esp
# return falls through to trapret...
.globl trapret
/*
* a forked process RETs here
* expects ESP to point to a Trapframe
*/
.globl trapret
trapret:
popal
popl %es
......@@ -28,6 +30,10 @@ trapret:
addl $0x8, %esp /* trapno and errcode */
iret
.globl forkret
forkret:
call forkret1
jmp trapret
.globl acpu
acpu:
......
......@@ -29,6 +29,8 @@ static __inline uint32_t read_ebp(void) __attribute__((always_inline));
static __inline uint32_t read_esp(void) __attribute__((always_inline));
static __inline void cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp);
static __inline uint64_t read_tsc(void) __attribute__((always_inline));
static __inline void cli(void) __attribute__((always_inline));
static __inline void sti(void) __attribute__((always_inline));
static __inline void
breakpoint(void)
......@@ -304,6 +306,18 @@ read_tsc(void)
return tsc;
}
static __inline void
cli(void)
{
__asm__ volatile("cli");
}
static __inline void
sti(void)
{
__asm__ volatile("sti");
}
struct PushRegs {
/* registers as pushed by pusha */
uint32_t reg_edi;
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论