[PATCH 3 of 5]

Juan Perez-Sanchez <[email protected]>
Newsgroups org.kernel.vger.linux-8086
Message-ID <CAD6VGuYXP8Wim7bVtjgmPuhVNqY0oKvaeP3pWRUTyG+zUF_KAw@mail.gmail.com>
Hi,

This patch makes:

-System call fork() did not preserved user registers SI and DI
for the child task, and getting user register BP was unnecessa-
rily complex. The code was greatly simplified and assembly
function fake_save_regs() was completely removed.

-Function tswitch() preserved registers BX and DX, but this is
not required by the calling conventions. The code was
simplified.

-Initialization of struct task_struct was repeated at several
places in the source tree. Now, function find_empty_process()
does some initialization.

-Code size was reduced by 128 bytes.

Greetings,

Juan
elks-2c.patch (text/x-patch, 13.9 KB)
diff -Nur elks.orig/arch/i86/boot/crt0.S elks/arch/i86/boot/crt0.S
--- elks.orig/arch/i86/boot/crt0.S	2014-10-08 13:43:54.000000000 -0500
+++ elks/arch/i86/boot/crt0.S	2014-10-13 12:43:45.000000000 -0500
@@ -56,7 +56,7 @@
 
 #ifndef CONFIG_ROMCODE
 	mov	ss,dx		! in ROMCODE stack is ready placed
-	mov	sp,#(_task + TASK_KSTKTOP)
+	mov	sp,#(_task + TASK_KSTKTOP - 10)
 #endif
 
 ! Space for temporary stack space _bootstack removed!!
diff -Nur elks.orig/arch/i86/kernel/process.c elks/arch/i86/kernel/process.c
--- elks.orig/arch/i86/kernel/process.c	2014-04-26 22:12:31.000000000 -0500
+++ elks/arch/i86/kernel/process.c	2014-10-13 13:16:47.000000000 -0500
@@ -9,42 +9,7 @@
 #include <arch/segment.h>
 #include <arch/asm-offsets.h>
 
-/*
- *	This function can only be called with SS=DS=ES=kernel DS
- *	CS=kernel CS. SS:SP is the relevant kernel stack (IRQ's are
- *	taken on 'current' kernel stack.
- *
- *	load_regs can also only be called from such a situation, thus
- *	we don't need to arse about with segment registers. The kernel isn't
- *	relocating.
- *
- *	To understand this you need to know how the compilers generate 8086
- *	stack frames. Functions normally start
- *
- *	push bp		! Save callers BP
- *	mov  bp,sp	! BP so we can use it to index registers
- *
- *	and end
- *
- *	mov sp,bp	! Fastest way to destroy local variables
- *	pop bp		! Restore callers BP
- *	ret		! Return address is top of stack now
- *
- *	save_regs() saves the callers registers and state then returns to
- *	the caller. It in effect freezes a copy of the caller context but
- *	doesn't prevent it being used temporarily beyond that as we do. 
- *
- *	load_regs() restores the callers context and returns skipping out of 
- *	schedule() [our faked setup] back to the right place. 
- *
- *	fake_save_regs builds a stack frame that returns a new task to a
- *	kernel address of our choice using its own stack/context.
- *
- * ELKS 0.76 7/1999  Fixed for ROMCODE-Version
- * Christian Mardm”ller  ([email protected])
- */
-
-#ifdef CONFIG_ROMCODE 
+#ifdef CONFIG_ROMCODE
 
 #define stashed_ds	[0]
 
@@ -70,10 +35,7 @@
 
 #endif
 
-typedef unsigned short int FsR;
-
 extern int do_signal(void);
-extern int fake_save_regs(FsR,FsR);
 
 void sig_check(void)
 {
@@ -81,6 +43,33 @@
         do_signal();
 }
 
+/*
+ *	tswitch();
+ *
+ *	This function can only be called with SS=DS=ES=kernel DS and
+ *	CS=kernel CS. SS:SP is the relevant kernel stack (IRQ's are
+ *	taken on 'current' kernel stack. Thus we don't need to arse about
+ *	with segment registers. The kernel isn't relocating.
+ *
+ *	To understand this you need to know how the compilers generate 8086
+ *	stack frames. Functions normally start
+ *
+ *	push bp		! Save callers BP
+ *	mov  bp,sp	! BP so we can use it to index registers
+ *
+ *	and end
+ *
+ *	mov sp,bp	! Fastest way to destroy local variables
+ *	pop bp		! Restore callers BP
+ *	ret		! Return address is top of stack now
+ *
+ *	tswitch() saves the "previous" task registers and state. It in effect
+ *	freezes a copy of the caller context. Then restores the "current"
+ *	context and returns running the current task.
+ *
+ * ELKS 0.76 7/1999  Fixed for ROMCODE-Version
+ * Christian Mardm”ller  ([email protected])
+ */
 #ifndef S_SPLINT_S
 #asm
 	.text
@@ -92,14 +81,10 @@
 	pushf
 	push di
 	push si
-	push bx
-	push dx
 	mov bx,_previous
 	mov TASK_KRNL_SP[bx],sp
 	mov bx,_current
 	mov sp,TASK_KRNL_SP[bx]
-	pop dx
-	pop bx
 	pop si
 	pop di
 	popf
@@ -226,63 +211,6 @@
 !
 !	Done.
 !
-
-	.globl _fake_save_regs
-!
-!	int used=fake_save_regs(sp,addr);
-!
-!	Build a fake return stack in kernel space so that
-!	we can have a new task start at a chosen kernel 
-!	function while on its kernel stack. We push the
-!	registers suitably for
-!
-_fake_save_regs:
-#if 0
-	push 	bp
-	mov	bp,sp
-	mov     bx,4[bp]	! new task ksp
-	mov	ax,6[bp]	! new task start address
-!
-!	Build a dummy stack return frame
-!
-	mov	-2[bx],ax	! Return address
-	mov	ax,[bp]		! Caller BP
-	mov	-4[bx],ax	! Save caller BP
-	mov	ax,bx		! Firstly get bx
-	sub	ax,#4		! This is the apparent BP. It points
-				! to caller BP and above it caller return
-	mov	-6[bx],ax	! goes here.
-!
-!	Register State
-!
-	pushf
-	pop	ax
-	mov	-8[bx],ax	! Flags
-	mov	-10[bx],di
-	mov 	-12[bx],si
-	mov	-14[bx],bx
-	mov	-16[bx],dx
-	mov	ax,#16
-	pop	bp
-	ret
-#else
-	push	bp
-	mov	bp,sp
-	mov     bx,4[bp]	! new task ksp
-	mov	ax,6[bp]	! new task start address
-	pop	bp
-
-	mov	-2[bx],ax	! Return address
-	mov	-4[bx],bp	! Save caller BP
-	pushf
-	pop	-6[bx]		! Flags
-	mov	-8[bx],di
-	mov 	-10[bx],si
-	mov	-12[bx],bx
-	mov	-14[bx],dx
-	mov	ax,#14
-	ret
-#endif
 #endasm
 #endif
 
@@ -338,26 +266,21 @@
  *	Make task t fork into kernel space. We are in kernel mode
  *	so we fork onto our kernel stack.
  */
- 
-void kfork_proc(register struct task_struct *t,char *addr)
+
+void kfork_proc(char *addr)
 {
-    memset(t, 0, sizeof(struct task_struct));
-    t->t_regs.ds = t->t_regs.ss = get_ds();
-    t->t_regs.ksp = ((__u16) t->t_kstack) + KSTACK_BYTES;
-    t->t_regs.ksp -= fake_save_regs((__u16)t->t_regs.ksp,(__u16)addr);
+    register struct task_struct *t;
 
-    t->state = TASK_UNINTERRUPTIBLE;
-    t->pid = get_pid();
-    t->t_kstackm = KSTACK_MAGIC;
-    t->prev_run = t->next_run = NULL;
+    t = find_empty_process();
 
-    wake_up_process(t);
-    schedule();
+    t->t_regs.cs = get_cs();
+    t->t_regs.ds = t->t_regs.ss = get_ds(); /* Run in kernel space */
+    arch_build_stack(t, addr);
 }
 
 /*
  *	Build a user return stack for exec*(). This is quite easy,
- *	especially as our syscall entry doesnt use the user stack. 
+ *	especially as our syscall entry doesnt use the user stack.
  */
 
 #define USER_FLAGS 0x3200		/* IPL 3, interrupt enabled */
@@ -447,26 +370,28 @@
  * we need to do to recover the user's bp.
  */
 
-extern void ret_from_syscall();		/* our return address */
-
-static void* saved_bp;			/* we have to recover user's bp */
-
-void arch_build_stack(struct task_struct *t)
-{
-    char *kstktop = (char *) t->t_kstack+KSTACK_BYTES;
+/*
+ *	arch_build_stack(t, addr);
+ *
+ * Build a fake return stack in kernel space so that
+ * we can have a new task start at a chosen kernel
+ * function while on its kernel stack. We push the
+ * registers suitably for
+ */
 
-/*@i3@*/ t->t_regs.ksp = kstktop - fake_save_regs(kstktop, ret_from_syscall);
+extern void ret_from_syscall();		/* our return address */
 
+void arch_build_stack(struct task_struct *t, char *addr)
 {
-#ifndef S_SPLINT_S
-#asm
-	mov	bx,[bp]	! bx = bp on entry to arch_build_stack
-	mov	bx,[bx]	! ax = bp on entry to do_fork = users bp (hopefully!)
-	mov	ax,[bx]	! ax = bp on entry to do_fork = users bp (hopefully!)
-	mov	_saved_bp,ax
-#endasm
-#endif
-}
+    register __u16 *tsp = (__u16 *)(t->t_kstack + KSTACK_BYTES - 10);
+    register __u16 *csp = (__u16 *)(current->t_kstack + KSTACK_BYTES - 14);
 
-    *(void**) (kstktop-4) = saved_bp;
+    t->t_regs.ksp = (__u16)tsp;
+    *tsp++ = *(csp + 6);	/* Initial value for SI register */
+    *tsp++ = *(csp + 5);	/* Initial value for DI register */
+    *tsp++ = 0x3202;		/* Initial value for FLAGS register */
+    *tsp++ = *csp;		/* Initial value for BP register */
+    if(addr == NULL)
+	addr = ret_from_syscall;
+    *tsp = addr;		/* Start execution address */
 }
diff -Nur elks.orig/arch/i86/kernel/system.c elks/arch/i86/kernel/system.c
--- elks.orig/arch/i86/kernel/system.c	2014-04-26 22:12:31.000000000 -0500
+++ elks/arch/i86/kernel/system.c	2014-10-11 16:07:46.000000000 -0500
@@ -28,8 +28,6 @@
 
 void setup_arch(seg_t *start, seg_t *end)
 {
-    register __ptask taskp;
-
 #ifndef S_SPLINT_S
 /*
  *	Save segments
@@ -53,16 +51,6 @@
 
     arch_segs.lowss = arch_segs.endss;
 
-/*
- *	arch dependent sched init. Set the kernel SP,
- *	as we will need this in interrupts.
- */	
-    taskp = &task[0];
-    taskp->t_regs.cs = get_cs();
-    taskp->t_regs.ds = taskp->t_regs.ss = get_ds(); /* Run in kernel space */
-    taskp->t_regs.ksp = ((__u16) taskp->t_kstack) + KSTACK_BYTES;
-    taskp->t_kstackm = KSTACK_MAGIC;
-	
 #ifdef CONFIG_COMPAQ_FAST
 
 /*
diff -Nur elks.orig/include/linuxmt/init.h elks/include/linuxmt/init.h
--- elks.orig/include/linuxmt/init.h	2014-04-26 22:12:31.000000000 -0500
+++ elks/include/linuxmt/init.h	2014-10-11 22:12:27.000000000 -0500
@@ -35,7 +35,7 @@
 extern void setup_mm(void);
 extern void device_setup(void);
 
-extern void kfork_proc(struct task_struct *,void ());
+extern void kfork_proc(void ());
 extern void arch_setup_kernel_stack(struct task_struct *);
 extern void setup_dev(register struct gendisk *);
 extern void mem_dev_init(void);
diff -Nur elks.orig/include/linuxmt/sched.h elks/include/linuxmt/sched.h
--- elks.orig/include/linuxmt/sched.h	2014-04-26 22:12:31.000000000 -0500
+++ elks/include/linuxmt/sched.h	2014-10-13 12:58:53.000000000 -0500
@@ -87,7 +87,7 @@
     sigset_t			signal;		/* Signal status */
     struct signal_struct	sig;		/* Signal block */
     int 			dumpable;	/* Can core dump */
-	
+
 #ifdef CONFIG_SWAP
     jiff_t			last_running;
 #endif
@@ -162,7 +162,8 @@
 
 extern void add_to_runqueue(struct task_struct *);
 
-extern void arch_build_stack(struct task_struct *);
+extern struct task_struct *find_empty_process(void);
+extern void arch_build_stack(struct task_struct *, char *);
 extern unsigned int get_ustack(struct task_struct *,int);
 extern void put_ustack(register struct task_struct *,int,int);
 
diff -Nur elks.orig/init/main.c elks/init/main.c
--- elks.orig/init/main.c	2014-04-26 22:12:31.000000000 -0500
+++ elks/init/main.c	2014-10-11 22:15:49.000000000 -0500
@@ -65,7 +65,8 @@
 
     printk("ELKS version %s\n", system_utsname.release);
 
-    kfork_proc(&task[1], init_task);
+    kfork_proc(init_task);
+    wake_up_process(&task[1]);
 
     /* 
      * We are now the idle task. We won't run unless no other process can run.
@@ -73,7 +74,6 @@
     while (1){
         schedule();
     }
-
 }
 
 static char args[] = "\0\0\0\0\0\0/bin/init\0\0";
diff -Nur elks.orig/kernel/fork.c elks/kernel/fork.c
--- elks.orig/kernel/fork.c	2014-04-26 22:12:31.000000000 -0500
+++ elks/kernel/fork.c	2014-10-13 12:56:41.000000000 -0500
@@ -5,13 +5,34 @@
 #include <linuxmt/mm.h>
 #include <linuxmt/sched.h>
 
-int task_slots_unused = MAX_TASKS - 2;
-struct task_struct *next_task_slot = &task[2];
+int task_slots_unused = MAX_TASKS;
+struct task_struct *next_task_slot = task;
+
+pid_t get_pid(void)
+{
+    register struct task_struct *p;
+    static pid_t last_pid = -1;
+
+repeat:
+    if (++last_pid < 0)
+        last_pid = 1;
+
+    p = &task[1];
+    do {
+        if (p->state == TASK_UNUSED)
+            continue;
+	if (p->pid == last_pid || p->pgrp == last_pid ||
+	    p->session == last_pid) {
+	    goto repeat;
+	}
+    } while (++p < &task[MAX_TASKS]);
+    return last_pid;
+}
 
 /*
  *	Find a free task slot.
  */
-static struct task_struct *find_empty_process(void)
+struct task_struct *find_empty_process(void)
 {
     register struct task_struct *t;
 
@@ -19,7 +40,7 @@
         printk("Only %d slots\n", task_slots_unused);
         if (!task_slots_unused || current->uid)
             return NULL;
-	}
+    }
     t = next_task_slot;
     while (t->state != TASK_UNUSED) {
         if (++t >= &task[MAX_TASKS])
@@ -27,31 +48,14 @@
     }
     next_task_slot = t;
     task_slots_unused--;
+    *t = *current;
+    t->state = TASK_UNINTERRUPTIBLE;
+    t->pid = get_pid();
+    t->t_kstackm = KSTACK_MAGIC;
+    t->next_run = t->prev_run = NULL;
     return t;
 }
 
-
-pid_t get_pid(void)
-{
-    register struct task_struct *p;
-    static pid_t last_pid = 0;
-
-repeat:
-    if (++last_pid < 0)
-        last_pid = 1;
-                
-    p = &task[0];
-    do {
-        if (p->state == TASK_UNUSED)
-            continue;
-	if (p->pid == last_pid || p->pgrp == last_pid ||
-	    p->session == last_pid) {
-	    goto repeat;
-	}
-    } while (++p < &task[MAX_TASKS]);
-    return last_pid;
-}
-
 /*
  *	Clone a process.
  */
@@ -66,13 +70,9 @@
     if((t = find_empty_process()) == NULL)
         return -EAGAIN;
 
-    /* Copy everything */
-
-    *t = *currentp;
-
     /* Fix up what's different */
 
-    /* 
+    /*
      * We do shared text.
      */
     (void) mm_realloc(currentp->mm.cseg);
@@ -92,19 +92,12 @@
 
 	t->t_regs.ds = t->t_regs.ss = t->mm.dseg;
     }
-    t->t_regs.ksp = ((__u16) t->t_kstack) + KSTACK_BYTES;
-
-    t->state = TASK_UNINTERRUPTIBLE;
-    t->pid = get_pid();
-    t->ppid = currentp->pid;
-    t->t_kstackm = KSTACK_MAGIC;
-    t->next_run = t->prev_run = NULL;
 
     /*
      *      Build a return stack for t.
      */
 
-    arch_build_stack(t);
+    arch_build_stack(t, NULL);
 
     /* Increase the reference count to all open files */
 
@@ -118,6 +111,7 @@
     t->fs.pwd->i_count++;
 
     /* Set up our family tree */
+    t->ppid = currentp->pid;
     t->p_parent = currentp;
     t->p_nextsib = t->p_child = NULL;
     t->child_lastend = t->lastend_status = 0;
diff -Nur elks.orig/kernel/sched.c elks/kernel/sched.c
--- elks.orig/kernel/sched.c	2014-10-08 13:43:54.000000000 -0500
+++ elks/kernel/sched.c	2014-10-13 09:28:34.000000000 -0500
@@ -11,6 +11,7 @@
 
 #include <linuxmt/kernel.h>
 #include <linuxmt/sched.h>
+#include <linuxmt/init.h>
 #include <linuxmt/timer.h>
 #include <linuxmt/string.h>
 
@@ -21,7 +22,8 @@
 __task task[MAX_TASKS];
 unsigned char nr_running;
 
-__ptask current, previous;
+__ptask current = task;
+__ptask previous;
 
 extern int intr_count;
 
@@ -272,23 +274,21 @@
 
 void sched_init(void)
 {
-    register struct task_struct *taskp;
+    register struct task_struct *t = task;
 
 /*
- *	Now create task 0 to be ourself.
+ *	Mark tasks 0-(MAX_TASKS-1) as not in use.
  */
-    taskp = &init_task;
-    taskp->state = TASK_RUNNING;
-    taskp->next_run = taskp->prev_run = taskp;
-
-    current = taskp;
-/*    nr_running = 0;*/
+    do {
+	t->state = TASK_UNUSED;
+    } while(++t < &task[MAX_TASKS]);
 
 /*
- *	Mark tasks 1-31 as not in use.
+ *	Now create task 0 to be ourself.
  */
+    kfork_proc(NULL);
 
-    while(++taskp < &task[MAX_TASKS])
-	taskp->state=TASK_UNUSED;
-
+    t = task;
+    t->state = TASK_RUNNING;
+    t->next_run = t->prev_run = t;
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.