From 2c5f7aba38f8e7207a81fdef36d7720bda9dc4e5 Mon Sep 17 00:00:00 2001
From: Russ Cox <rsc@swtch.com>
Date: Sat, 11 Jul 2009 19:28:29 -0700
Subject: [PATCH] initproc, usegment, swtch tweaks

---
 defs.h    |  5 ++--
 proc.c    | 85 +++++++++++++++++++++++++------------------------------
 swtch.S   |  8 ++++--
 trapasm.S |  8 ------
 4 files changed, 46 insertions(+), 60 deletions(-)

diff --git a/defs.h b/defs.h
index cb47716..09fa467 100644
--- a/defs.h
+++ b/defs.h
@@ -52,7 +52,7 @@ int             writei(struct inode*, char*, uint, uint);
 // ide.c
 void            ideinit(void);
 void            ideintr(void);
-void            iderw(struct buf *);
+void            iderw(struct buf*);
 
 // ioapic.c
 void            ioapicenable(int irq, int cpu);
@@ -109,7 +109,7 @@ void            wakeup(void*);
 void            yield(void);
 
 // swtch.S
-void            swtch(struct context**, struct context**);
+void            swtch(struct context**, struct context*);
 
 // spinlock.c
 void            acquire(struct spinlock*);
@@ -151,7 +151,6 @@ void            uartinit(void);
 void            uartintr(void);
 void            uartputc(int);
 
-
 // number of elements in fixed-size array
 #define NELEM(x) (sizeof(x)/sizeof((x)[0]))
 
diff --git a/proc.c b/proc.c
index 554ad28..aa6c4ec 100644
--- a/proc.c
+++ b/proc.c
@@ -15,7 +15,7 @@ static struct proc *initproc;
 
 int nextpid = 1;
 extern void forkret(void);
-extern void forkret1(struct trapframe*);
+extern void trapret(void);
 
 void
 pinit(void)
@@ -30,19 +30,18 @@ static struct proc*
 allocproc(void)
 {
   struct proc *p;
+  char *sp;
 
   acquire(&ptable.lock);
-  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
-    if(p->state == UNUSED){
-      p->state = EMBRYO;
-      p->pid = nextpid++;
+  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
+    if(p->state == UNUSED)
       goto found;
-    }
-  }
   release(&ptable.lock);
   return 0;
 
 found:
+  p->state = EMBRYO;
+  p->pid = nextpid++;
   release(&ptable.lock);
 
   // Allocate kernel stack if necessary.
@@ -50,11 +49,20 @@ found:
     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));
+  sp = p->kstack + KSTACKSIZE;
+  
+  // Leave room for trap frame.
+  sp -= sizeof *p->tf;
+  p->tf = (struct trapframe*)sp;
+  
+  // Set up new context to start executing at forkret,
+  // which returns to trapret (see below).
+  sp -= 4;
+  *(uint*)sp = (uint)trapret;
+
+  sp -= sizeof *p->context;
+  p->context = (struct context*)sp;
+  memset(p->context, 0, sizeof *p->context);
   p->context->eip = (uint)forkret;
   return p;
 }
@@ -79,19 +87,16 @@ growproc(int n)
 }
 
 // Set up CPU's kernel segment descriptors.
+// Run once at boot time on each CPU.
 void
 ksegment(void)
 {
   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;
+  c1->gdt[SEG_KCPU] = SEG(STA_W, (uint)(&c1->tls+1), 0xffffffff, 0);
   lgdt(c1->gdt, sizeof(c1->gdt));
   loadfsgs(SEG_KCPU << 3);
   
@@ -106,23 +111,12 @@ void
 usegment(void)
 {
   pushcli();
-  c->ts.ss0 = SEG_KDATA << 3;
-  if(cp)
-    c->ts.esp0 = (uint)(cp->kstack + KSTACKSIZE);
-  else
-    c->ts.esp0 = 0xffffffff;
-
-  if(cp){
-    c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (uint)cp->mem, cp->sz-1, DPL_USER);
-    c->gdt[SEG_UDATA] = SEG(STA_W, (uint)cp->mem, cp->sz-1, DPL_USER);
-  } else {
-    c->gdt[SEG_UCODE] = SEG_NULL;
-    c->gdt[SEG_UDATA] = SEG_NULL;
-  }
+  c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (uint)cp->mem, cp->sz-1, DPL_USER);
+  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;
-
-  lgdt(c->gdt, sizeof(c->gdt));
+  c->ts.ss0 = SEG_KDATA << 3;
+  c->ts.esp0 = (uint)cp->kstack + KSTACKSIZE;
   ltr(SEG_TSS << 3);
   popcli();
 }
@@ -171,7 +165,7 @@ void
 userinit(void)
 {
   struct proc *p;
-  extern uchar _binary_initcode_start[], _binary_initcode_size[];
+  extern char _binary_initcode_start[], _binary_initcode_size[];
   
   p = allocproc();
   initproc = p;
@@ -179,6 +173,7 @@ userinit(void)
   // Initialize memory from initcode.S
   p->sz = PAGE;
   p->mem = kalloc(p->sz);
+  memset(p->mem, 0, p->sz);
   memmove(p->mem, _binary_initcode_start, (int)_binary_initcode_size);
 
   memset(p->tf, 0, sizeof(*p->tf));
@@ -210,7 +205,7 @@ scheduler(void)
   struct proc *p;
 
   for(;;){
-    // Enable interrupts on this processor, in lieu of saving intena.
+    // Enable interrupts on this processor.
     sti();
 
     // Loop over process table looking for process to run.
@@ -225,36 +220,35 @@ scheduler(void)
       cp = p;
       usegment();
       p->state = RUNNING;
-      swtch(&c->context, &p->context);
+      swtch(&c->context, p->context);
 
       // Process is done running for now.
       // It should have changed its p->state before coming back.
       cp = 0;
-      usegment();
     }
     release(&ptable.lock);
 
   }
 }
 
-// Enter scheduler.  Must already hold ptable.lock
+// Enter scheduler.  Must hold only ptable.lock
 // and have changed cp->state.
 void
 sched(void)
 {
   int intena;
 
-  if(readeflags()&FL_IF)
-    panic("sched interruptible");
-  if(cp->state == RUNNING)
-    panic("sched running");
   if(!holding(&ptable.lock))
     panic("sched ptable.lock");
   if(c->ncli != 1)
     panic("sched locks");
+  if(cp->state == RUNNING)
+    panic("sched running");
+  if(readeflags()&FL_IF)
+    panic("sched interruptible");
 
   intena = c->intena;
-  swtch(&cp->context, &c->context);
+  swtch(&cp->context, c->context);
   c->intena = intena;
 }
 
@@ -262,7 +256,7 @@ sched(void)
 void
 yield(void)
 {
-  acquire(&ptable.lock);
+  acquire(&ptable.lock);  //DOC: yieldlock
   cp->state = RUNNABLE;
   sched();
   release(&ptable.lock);
@@ -275,9 +269,8 @@ forkret(void)
 {
   // Still holding ptable.lock from scheduler.
   release(&ptable.lock);
-
-  // Jump into assembly, never to return.
-  forkret1(cp->tf);
+  
+  // Return to "caller", actually trapret (see allocproc).
 }
 
 // Atomically release lock and sleep on chan.
diff --git a/swtch.S b/swtch.S
index ada98f3..8751317 100644
--- a/swtch.S
+++ b/swtch.S
@@ -1,5 +1,7 @@
-#   void swtch(struct context **old, struct context **new);
-#  
+# Context switch
+#
+#   void swtch(struct context **old, struct context *new);
+# 
 # Save current register context in old
 # and then load register context from new.
 
@@ -16,7 +18,7 @@ swtch:
 
   # Switch stacks
   movl %esp, (%eax)
-  movl (%edx), %esp
+  movl %edx, %esp
 
   # Load new callee-save registers
   popl %edi
diff --git a/trapasm.S b/trapasm.S
index 983163d..1cb2ce6 100644
--- a/trapasm.S
+++ b/trapasm.S
@@ -35,11 +35,3 @@ trapret:
   popl %ds
   addl $0x8, %esp  # trapno and errcode
   iret
-
-  # A forked process switches to user mode by calling
-  # forkret1(tf), where tf is the trap frame to use.
-.globl forkret1
-forkret1:
-  movl 4(%esp), %esp
-  jmp trapret
-
-- 
GitLab