Add TODO item.
[bertos.git] / kern / proc.c
index 4099313d46c783c044005f5f8de79d9edbd9362e..495ca735e5d2cedc650eedb4a848fb53b622e1ee 100755 (executable)
@@ -3,7 +3,7 @@
  * <!--
  * Copyright 2001,2004 Develer S.r.l. (http://www.develer.com/)
  * Copyright 1999,2000,2001 Bernardo Innocenti <bernie@develer.com>
- * This file is part of DevLib - See devlib/README for information.
+ * This file is part of DevLib - See README.devlib for information.
  * -->
  *
  * \brief Simple realtime multitasking scheduler.
 
 /*#*
  *#* $Log$
+ *#* Revision 1.29  2006/02/24 01:17:05  bernie
+ *#* Update for new emulator.
+ *#*
+ *#* Revision 1.28  2006/02/21 16:06:55  bernie
+ *#* Cleanup/update process scheduling.
+ *#*
+ *#* Revision 1.27  2005/11/04 16:20:02  bernie
+ *#* Fix reference to README.devlib in header.
+ *#*
+ *#* Revision 1.26  2005/04/11 19:10:28  bernie
+ *#* Include top-level headers from cfg/ subdir.
+ *#*
+ *#* Revision 1.25  2005/03/15 00:20:54  bernie
+ *#* proc_schedule(): New sanity check.
+ *#*
+ *#* Revision 1.24  2005/01/08 09:20:54  bernie
+ *#* Remove unused variable.
+ *#*
+ *#* Revision 1.23  2004/12/13 12:07:06  bernie
+ *#* DISABLE_IRQSAVE/ENABLE_IRQRESTORE: Convert to IRQ_SAVE_DISABLE/IRQ_RESTORE.
+ *#*
+ *#* Revision 1.22  2004/12/13 11:51:08  bernie
+ *#* DISABLE_INTS/ENABLE_INTS: Convert to IRQ_DISABLE/IRQ_ENABLE.
+ *#*
+ *#* Revision 1.21  2004/11/28 23:20:25  bernie
+ *#* Remove obsolete INITLIST macro.
+ *#*
+ *#* Revision 1.20  2004/11/16 22:37:14  bernie
+ *#* Replace IPTR with iptr_t.
+ *#*
+ *#* Revision 1.19  2004/10/19 11:47:39  bernie
+ *#* Kill warnings when !CONFIG_PROC_MONITOR.
+ *#*
+ *#* Revision 1.18  2004/10/19 08:54:43  bernie
+ *#* Initialize forbid_cnt; Formatting/comments fixes.
+ *#*
  *#* Revision 1.17  2004/10/19 08:47:13  bernie
  *#* proc_rename(), proc_forbid(), proc_permit(): New functions.
  *#*
 
 #include "proc_p.h"
 #include "proc.h"
-#include "cpu.h"
-#include "event.h"
-#include "hw.h"
-#include <debug.h>
-#include <arch_config.h>  /* ARCH_EMUL */
-#include <macros.h>  /* ABS() */
+//#include "hw.h"
+#include <mware/event.h>
+#include <cfg/cpu.h>
+#include <cfg/debug.h>
+#include <cfg/arch_config.h>  /* ARCH_EMUL */
+#include <cfg/macros.h>  /* ABS() */
 
 #include <string.h> /* memset() */
 
@@ -112,19 +148,23 @@ uint16_t Quantum;
 extern List StackFreeList;
 #endif
 
-/* The main process (the one that executes main()) */
+/*! The main process (the one that executes main()). */
 struct Process MainProcess;
 
 
-static void proc_init_struct(Processproc)
+static void proc_init_struct(Process *proc)
 {
-       /* Avoid warning for unused argument */
+       /* Avoid warning for unused argument. */
        (void)proc;
 
 #if CONFIG_KERN_SIGNALS
        proc->sig_recv = 0;
 #endif
 
+#if CONFIG_KERN_PREEMPTIVE
+       proc->forbid_cnt = 0;
+#endif
+
 #if CONFIG_KERN_HEAP
        proc->flags = 0;
 #endif
@@ -133,7 +173,7 @@ static void proc_init_struct(Process* proc)
 
 void proc_init(void)
 {
-       INITLIST(&ProcReadyList);
+       LIST_INIT(&ProcReadyList);
 
 #if CONFIG_KERN_MONITOR
        monitor_init();
@@ -157,10 +197,9 @@ void proc_init(void)
  * \return Process structure of new created process
  *         if successful, NULL otherwise.
  */
-struct Process *proc_new_with_name(UNUSED(const char*, name), void (*entry)(void), IPTR data, size_t stacksize, cpustack_t *stack_base)
+struct Process *proc_new_with_name(UNUSED(const char *, name), void (*entry)(void), iptr_t data, size_t stacksize, cpustack_t *stack_base)
 {
        Process *proc;
-       cpuflags_t flags;
        size_t i;
        size_t proc_size_words = ROUND2(sizeof(Process), sizeof(cpustack_t)) / sizeof(cpustack_t);
 #if CONFIG_KERN_HEAP
@@ -168,12 +207,10 @@ struct Process *proc_new_with_name(UNUSED(const char*, name), void (*entry)(void
 #endif
 
 #if (ARCH & ARCH_EMUL)
-       /* Ignore stack provided by caller
-       * and use the large enough default instead
-       */
-       stack_base = (cpustack_t *)StackFreeList.head;
-       REMOVE((Node *)stack_base);
-       stacksize = DEF_STACKSIZE;
+       /* Ignore stack provided by caller and use the large enough default instead. */
+       stack_base = (cpustack_t *)LIST_HEAD(&StackFreeList);
+       REMOVE(LIST_HEAD(&StackFreeList));
+       stacksize = CONFIG_KERN_DEFSTACKSIZE;
 #elif CONFIG_KERN_HEAP
        /* Did the caller provide a stack for us? */
        if (!stack_base)
@@ -234,9 +271,7 @@ struct Process *proc_new_with_name(UNUSED(const char*, name), void (*entry)(void
                CPU_PUSH_WORD(proc->stack, CPU_REG_INIT_VALUE(i));
 
        /* Add to ready list */
-       DISABLE_IRQSAVE(flags);
-       SCHED_ENQUEUE(proc);
-       ENABLE_IRQRESTORE(flags);
+       ATOMIC(SCHED_ENQUEUE(proc));
 
 #if CONFIG_KERN_MONITOR
        monitor_add(proc, name, stack_base, stacksize);
@@ -250,6 +285,8 @@ void proc_rename(struct Process *proc, const char *name)
 {
 #if CONFIG_KERN_MONITOR
        monitor_rename(proc, name);
+#else
+       (void)proc; (void)name;
 #endif
 }
 
@@ -268,15 +305,20 @@ void proc_schedule(void)
         * the compiler might put them on the stack of the process
         * being switched out.
         */
-       static Process *old_process;
+       static struct Process *old_process;
        static cpuflags_t flags;
 
        /* Remember old process to save its context later */
        old_process = CurrentProcess;
 
+#ifdef IRQ_RUNNING
+       /* Scheduling in interrupts is a nono. */
+       ASSERT(!IRQ_RUNNING());
+#endif
+
        /* Poll on the ready queue for the first ready process */
-       DISABLE_IRQSAVE(flags);
-       while (!(CurrentProcess = (struct Process*)REMHEAD(&ProcReadyList)))
+       IRQ_SAVE_DISABLE(flags);
+       while (!(CurrentProcess = (struct Process *)list_remHead(&ProcReadyList)))
        {
                /*
                 * Make sure we physically reenable interrupts here, no matter what
@@ -284,22 +326,23 @@ void proc_schedule(void)
                 * are idle-spinning, we must allow interrupts, otherwise no
                 * process will ever wake up.
                 *
-                * \todo If there was a way to code sig_wait so that it does not
+                * \todo If there was a way to write sig_wait() so that it does not
                 * disable interrupts while waiting, there would not be any
                 * reason to do this.
                 */
-               ENABLE_INTS;
+               IRQ_ENABLE;
                SCHEDULER_IDLE;
-               DISABLE_INTS;
+               IRQ_DISABLE;
        }
-       ENABLE_IRQRESTORE(flags);
+       IRQ_RESTORE(flags);
 
-       /* Optimization: don't switch contexts when the active
+       /*
+        * Optimization: don't switch contexts when the active
         * process has not changed.
         */
        if (CurrentProcess != old_process)
        {
-               static cpustack_tdummy;
+               static cpustack_t *dummy;
 
 #if CONFIG_KERN_PREEMPTIVE
                /* Reset quantum for this process */
@@ -325,8 +368,13 @@ void proc_schedule(void)
  */
 void proc_exit(void)
 {
+#if CONFIG_KERN_MONITOR
+       monitor_remove(CurrentProcess);
+#endif
+
 #if CONFIG_KERN_HEAP
-       /* The following code is BROKEN.
+       /*
+        * The following code is BROKEN.
         * We are freeing our own stack before entering proc_schedule()
         * BAJO: A correct fix would be to rearrange the scheduler with
         *  an additional parameter which frees the old stack/process
@@ -338,21 +386,18 @@ void proc_exit(void)
 #endif
 
 #if (ARCH & ARCH_EMUL)
-#error This is wrong
+#warning This is wrong
        /* Reinsert process stack in free list */
        ADDHEAD(&StackFreeList, (Node *)(CurrentProcess->stack
-               - (DEF_STACKSIZE / sizeof(cpustack_t))));
+               - (CONFIG_KERN_DEFSTACKSIZE / sizeof(cpustack_t))));
 
-       /* NOTE: At this point the first two words of what used
+       /*
+        * NOTE: At this point the first two words of what used
         * to be our stack contain a list node. From now on, we
         * rely on the compiler not reading/writing the stack.
         */
 #endif /* ARCH_EMUL */
 
-#if CONFIG_KERN_MONITOR
-       monitor_remove(CurrentProcess);
-#endif
-
        CurrentProcess = NULL;
        proc_schedule();
        /* not reached */
@@ -367,9 +412,9 @@ void proc_switch(void)
        /* Just like proc_schedule, this function must not have auto variables. */
        static cpuflags_t flags;
 
-       DISABLE_IRQSAVE(flags);
+       IRQ_SAVE_DISABLE(flags);
        SCHED_ENQUEUE(CurrentProcess);
-       ENABLE_IRQRESTORE(flags);
+       IRQ_RESTORE(flags);
 
        proc_schedule();
 }
@@ -386,7 +431,7 @@ struct Process *proc_current(void)
 /*!
  * Get the pointer to the user data of the current process
  */
-IPTR proc_current_user_data(void)
+iptr_t proc_current_user_data(void)
 {
        return CurrentProcess->user_data;
 }
@@ -425,6 +470,8 @@ void proc_permit(void)
        --CurrentProcess->forbid_cnt;
 }
 
+#endif /* CONFIG_KERN_PREEMPTIVE */
+
 
 #if 0 /* Simple testcase for the scheduler */