linux-8086.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Juan Perez-Sanchez <lithoxs@gmail.com>
To: linux-8086 <linux-8086@vger.kernel.org>
Subject: [PATCH] Improvements in speed and readability of fork functions
Date: Sat, 7 Jul 2012 09:59:00 -0500	[thread overview]
Message-ID: <CAD6VGube6U-p027UFhxtRjLFy4KWYkYvG2s=YmJABRn7t2oncQ@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1776 bytes --]

Hi,

   Patch to make fork functions faster. Also improve readability of
schedule() function.

Greetings,

Juan

PREVIOUS OPERATION AND BUGS

1. Function "kernel/fork.c/find_empty_process()" search for an empty
slot in "task" array. It examined every slot in the array and returned
the index of the last empty slot, a very inefficient process. It also
calculates the amount of empty slots.

2. Function "kernel/fork.c/get_pid()" returns a unique id number. It
checked that the id number is unique by looking for it in all slots of
the task array, even those marked as unused. It ran through the array
using an index.

3. Function "kernel/sched.c/schedule()" used 2 different variables
(prev and currentp) to hold the same information. Also, there was an
unused variable at the top level of file sched.c.

NEW OPERATION

1. A new variable keeps track of the amount of empty slots, modifying
its value as slots are taken or released. Another new variable is a
pointer to a slot very likely to be empty. The search stops with the
first unused slot found, uses and return a pointer to "struct
task_struct" instead of an integer index. As result, the new function
is faster and more compact.

2. The new get_pid function does not check empty slots, and uses a
pointer to "struct task_struct" instead of an integer index. Thus, it
is faster and more compact.

3. In file schedule, consolidated the use of two variables with only
one, improving readability. Removed unused top level variable.

OTHER CHANGES

1. A small optimization to reduce code size was done in files
irqtab.c, process.c and printk.c. There is a reduction in code size of
48 bytes.

 The Image builded without errors. The kernel was tested with QEMU and
dioscuri emulators. Also in a PPro pc booting from floppy.

[-- Attachment #2: elksK.patch --]
[-- Type: application/octet-stream, Size: 7370 bytes --]

diff -Nurb elks.orig/arch/i86/kernel/irqtab.c elks/arch/i86/kernel/irqtab.c
--- elks.orig/arch/i86/kernel/irqtab.c	2012-06-28 23:36:16.000000000 -0500
+++ elks/arch/i86/kernel/irqtab.c	2012-06-30 21:54:44.000000000 -0500
@@ -78,12 +78,10 @@
 
 
 #ifndef CONFIG_CONSOLE_BIOS
-	lea ax,_irq1      ;keyboard  
 	seg es
-	mov [36],ax
-	mov ax,cs
+        mov [36],#_irq1   ;keyboard
 	seg es
-	mov [38],ax
+        mov [38],cs
 #endif
 
 #if 0	
@@ -95,12 +93,10 @@
 	mov [42],ax
 #endif	
 
-	lea ax,_irq3      ;com2
 	seg es
-	mov [44],ax
-	mov ax,cs
+        mov [44],#_irq3   ;com2
 	seg es
-	mov [46],ax
+        mov [46],cs
 	
 	lea ax,_irq4     ;com1
 	seg es
diff -Nurb elks.orig/arch/i86/kernel/process.c elks/arch/i86/kernel/process.c
--- elks.orig/arch/i86/kernel/process.c	2012-06-28 23:36:05.000000000 -0500
+++ elks/arch/i86/kernel/process.c	2012-06-30 21:28:09.000000000 -0500
@@ -206,24 +206,22 @@
 !
 _ret_from_syscall:
 	cli
-	mov	dx,ax
 	mov	bx,_current
 !
-!	At this point, the kernel stack is empty. Thus, there in no
+!	At this point, the kernel stack is empty. Thus, there is no
 !       need to save the kernel stack pointer.
 !
 	mov 	sp,TASK_USER_SP[bx]
-	mov	ax,TASK_USER_SS[bx]
+	mov	bx,TASK_USER_SS[bx]
 !
 !	User segment recovery
 !
-	mov	ds,ax
-	mov	es,ax
-	mov	ss,ax
+	mov	ds,bx
+	mov	es,bx
+	mov	ss,bx
 !
 !	return with error info.
 !
-	mov	ax,dx
 	iret
 !
 !	Done.
@@ -272,19 +270,17 @@
 	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	ax,[bp]		! Caller BP
-	mov	-4[bx],ax	! Save caller BP
+	mov	-4[bx],bp	! Save caller BP
 	pushf
-	pop	ax
-	mov	-6[bx],ax	! Flags
+	pop	-6[bx]		! Flags
 	mov	-8[bx],di
 	mov 	-10[bx],si
 	mov	-12[bx],bx
 	mov	-14[bx],dx
 	mov	ax,#14
-	pop	bp
 	ret
 #endif
 #endasm
@@ -465,8 +461,7 @@
 #ifndef S_SPLINT_S
 #asm
 	mov	bx,[bp]	! bx = bp on entry to arch_build_stack
-	mov	ax,[bx]	! ax = bp on entry to do_fork = users bp (hopefully!)
-	mov	bx,ax
+	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
diff -Nurb elks.orig/kernel/exit.c elks/kernel/exit.c
--- elks.orig/kernel/exit.c	2012-05-11 13:26:27.000000000 -0500
+++ elks/kernel/exit.c	2012-06-30 00:05:11.000000000 -0500
@@ -10,6 +10,9 @@
 #include <linuxmt/errno.h>
 #include <linuxmt/mm.h>
 
+extern int task_slots_unused;
+extern struct task_struct *next_task_slot;
+
 /* Note: sys_wait only keeps *one* task in the task_struct right now...
  * this is different than V7 symantics I think, but good enough for 0.0.51
  * Whoops - we have to do wait3 for now :) 
@@ -109,6 +112,8 @@
     /* Now the task should never run again... - I hope this can still
      * be used outside of an int... :) */
     current->state = TASK_UNUSED;
+    next_task_slot = current;
+    task_slots_unused++;
     wake_up(&parent->child_wait);
     schedule();
     panic("Returning from sys_exit!\n");
diff -Nurb elks.orig/kernel/fork.c elks/kernel/fork.c
--- elks.orig/kernel/fork.c	2012-05-11 13:26:27.000000000 -0500
+++ elks/kernel/fork.c	2012-06-30 00:05:11.000000000 -0500
@@ -5,31 +5,29 @@
 #include <linuxmt/mm.h>
 #include <linuxmt/sched.h>
 
+int task_slots_unused = MAX_TASKS - 2;
+struct task_struct *next_task_slot = &task[2];
+
 /*
  *	Find a free task slot.
  */
-static pid_t find_empty_process(void)
+static struct task_struct *find_empty_process(void)
 {
-/*      register pid_t i, unused = 0; */
-    register char *pi;
-    register char *punused;
-    pid_t n;
+    register struct task_struct *t;
 
-    pi = punused = 0;
-    do {
-	if (task[(int)pi].state == TASK_UNUSED) {
-	    punused++;
-	    n = (int)pi;
+    if (task_slots_unused <= 1) {
+        printk("Only %d slots\n", task_slots_unused);
+        if (!task_slots_unused || current->uid)
+            return NULL;
 	}
-    } while (((int)(++pi)) < MAX_TASKS);
-
-    if (((int)punused) <= 1) {
-	printk("Only %d slots\n", (int)punused);
-	if (!punused || current->uid)
-	    return -EAGAIN;
+    t = next_task_slot;
+    while (t->state != TASK_UNUSED) {
+        if (++t >= &task[MAX_TASKS])
+            t = &task[1];
     }
-
-    return n;
+    next_task_slot = t;
+    task_slots_unused--;
+    return t;
 }
 
 
@@ -37,21 +35,20 @@
 {
     register struct task_struct *p;
     static pid_t last_pid = 0;
-/*      register int i; */
-    register char *pi;
 
 repeat:
-    if ( (++last_pid & 0x7fff) == 0 )
+    if (++last_pid < 0)
         last_pid = 1;
                 
-    pi = 0;
+    p = &task[0];
     do {
-	p = &task[(int)pi];
+        if (p->state == TASK_UNUSED)
+            continue;
 	if (p->pid == last_pid || p->pgrp == last_pid ||
 	    p->session == last_pid) {
 	    goto repeat;
 	}
-    } while (((int)(++pi)) < MAX_TASKS);
+    } while (++p < &task[MAX_TASKS]);
     return last_pid;
 }
 
@@ -62,14 +59,12 @@
 pid_t do_fork(int virtual)
 {
     register struct task_struct *t;
-    pid_t i = find_empty_process(), j;
+    pid_t j;
     struct file *filp;
     register __ptask currentp = current;
 
-    if (i < 0)
-	return i;
-
-    t = &task[i];
+    if((t = find_empty_process()) == NULL)
+        return -EAGAIN;
 
     /* Copy everything */
 
@@ -90,6 +85,8 @@
 	if (t->mm.dseg == NULL) {
 	    mm_free(currentp->mm.cseg);
 	    t->state = TASK_UNUSED;
+            task_slots_unused++;
+            next_task_slot = t;
 	    return -ENOMEM;
 	}
 
diff -Nurb elks.orig/kernel/printk.c elks/kernel/printk.c
--- elks.orig/kernel/printk.c	2012-05-11 13:26:27.000000000 -0500
+++ elks/kernel/printk.c	2012-06-30 14:10:09.000000000 -0500
@@ -44,10 +44,10 @@
 
 static void kputs(register char *buf)
 {
-    char ch, *p;
-
 #ifdef CONFIG_DCON_ANSI_PRINTK
 
+    char *p;
+
     /* Colourizing */
 
     static char colour[8] = { 27, '[', '3', '0', ';', '4', '0', 'm' };
@@ -64,8 +64,8 @@
 
 #endif
 
-    while ((ch = *buf++))
-	kputchar(ch);
+    while (*buf)
+	kputchar(*buf++);
 }
 
 /************************************************************************
diff -Nurb elks.orig/kernel/sched.c elks/kernel/sched.c
--- elks.orig/kernel/sched.c	2012-06-28 23:36:16.000000000 -0500
+++ elks/kernel/sched.c	2012-06-30 20:07:28.000000000 -0500
@@ -20,7 +20,7 @@
 __task task[MAX_TASKS];
 unsigned char nr_running;
 
-__ptask current, next, previous;
+__ptask current, previous;
 
 extern int intr_count;
 
@@ -79,7 +79,6 @@
 {
     register __ptask prev;
     register __ptask next;
-    __ptask currentp = current;
     jiff_t timeout = 0L;
 
     prev = current;
@@ -87,7 +86,7 @@
 
     if (prev->t_kstackm != KSTACK_MAGIC)
         panic("Process %d exceeded kernel stack limit! magic %x\n", 
-            currentp->pid, currentp->t_kstackm);
+            prev->pid, prev->t_kstackm);
 
     /* We have to let a task exit! */
     if (prev->state == TASK_EXITING)
@@ -122,7 +121,7 @@
         next = next->next_run;
     }
 
-    if (next != currentp) {
+    if (next != prev) {
         struct timer_list timer;
 
         if (timeout) {
@@ -161,7 +160,7 @@
      * quite legal. We just dont switch then */
 /*     if (intr_count > 0) */
         printk("Aiee: scheduling in interrupt %d - %d %d\n",
-           intr_count, currentp->pid, prev->pid);
+           intr_count, next->pid, prev->pid);
 }
 
 struct timer_list tl_list = { NULL, NULL, 0L, 0, NULL };

                 reply	other threads:[~2012-07-07 14:59 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAD6VGube6U-p027UFhxtRjLFy4KWYkYvG2s=YmJABRn7t2oncQ@mail.gmail.com' \
    --to=lithoxs@gmail.com \
    --cc=linux-8086@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).