preempt: irq supervisor draft
authorbernie <bernie@38d2e660-2303-0410-9eaa-f027e97ec537>
Sun, 17 Aug 2008 13:49:48 +0000 (13:49 +0000)
committerbernie <bernie@38d2e660-2303-0410-9eaa-f027e97ec537>
Sun, 17 Aug 2008 13:49:48 +0000 (13:49 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@1646 38d2e660-2303-0410-9eaa-f027e97ec537

app/demo/cfg/cfg_kern.h
app/demo/demo.mk
bertos/cfg/cfg_kern.h
bertos/emul/timer_posix.c
bertos/emul/timer_qt.c
bertos/kern/preempt.c
bertos/kern/proc.c
bertos/kern/proc.h

index 8dbd6608bb0f40cf27b0bdc16c63cb3965161231..e1a0c6cc262ba8336fcf25601830b7d3d9a64f78 100644 (file)
 #define CONFIG_KERN_SCHED       (1)
 #define CONFIG_KERN_SIGNALS     (1    && CONFIG_KERN_SCHED)
 #define CONFIG_KERN_TIMER       (1)
+#define CONFIG_KERN_IRQ         (1)
 #define CONFIG_KERN_HEAP        (0)
 #define CONFIG_KERN_SEMAPHORES  (0    && CONFIG_KERN_SIGNALS)
 #define CONFIG_KERN_MONITOR     (1    && CONFIG_KERN_SCHED)
+#define CONFIG_KERN_PREEMPT     (1    && CONFIG_KERN_SCHED && CONFIG_KERN_TIMER && CONFIG_KERN_IRQ)
 /*\}*/
 
-/* EXPERIMENTAL */
-#define CONFIG_KERN_PREEMPT     (1    && CONFIG_KERN_SCHED && CONFIG_KERN_TIMER)
-
 /* OBSOLETE */
 #define CONFIG_KERN_PREEMPTIVE CONFIG_KERN_PREEMPT
 
index a66e0f893723f2b8b628d27a80f3612ceffd531c..672de108a019f3bdda2919b8eb646510343bb198 100644 (file)
@@ -18,8 +18,8 @@ demo_DEBUG = 1
 TRG += demo
 
 # FIXME: we want to use g++ for C source too
-CC = g++
-CXX = g++
+CC = g++-4.1
+CXX = g++-4.1
 
 demo_CXXSRC = \
        bertos/emul/emul.cpp \
index f54d0f7ed0300c8dd0fa5bd07b31ad60110577ff..4b2286b364f60ac0315192254a25486fa33bf6db 100644 (file)
 #define CONFIG_KERN_SCHED       (0)
 #define CONFIG_KERN_SIGNALS     (0    && CONFIG_KERN_SCHED)
 #define CONFIG_KERN_TIMER       (0)
+#define CONFIG_KERN_IRQ         (0)
 #define CONFIG_KERN_HEAP        (0)
 #define CONFIG_KERN_SEMAPHORES  (0    && CONFIG_KERN_SIGNALS)
 #define CONFIG_KERN_MONITOR     (0    && CONFIG_KERN_SCHED)
-/*\}*/
+#define CONFIG_KERN_PREEMPT     (0    && CONFIG_KERN_SCHED && CONFIG_KERN_TIMER && CONFIG_KERN_IRQ)
 
 /* EXPERIMENTAL */
-#define CONFIG_KERN_PREEMPT     (0    && CONFIG_KERN_SCHED && CONFIG_KERN_TIMER)
 
 /* OBSOLETE */
 #define CONFIG_KERN_PREEMPTIVE CONFIG_KERN_PREEMPT
 
-/// Time sharing quantum in timer ticks.
-#define CONFIG_KERN_QUANTUM     50
+/// [ms] Time sharing quantum (a prime number prevents interference effects)
+#define CONFIG_KERN_QUANTUM     47
 
 /// Module logging level.
 #define KERN_LOG_LEVEL      LOG_LVL_ERR
index c372bae1c8b6db7b51a70dfeac34e40cb9bc2bfc..ede534063a3fd05100acebe729dc5ed2b18a02ae 100644 (file)
@@ -48,6 +48,9 @@ void timer_isr(int);
 /// HW dependent timer initialization.
 static void timer_hw_init(void)
 {
+#if CONFIG_KERN_IRQ
+       irq_register(SIGALRM, timer_isr);
+#else // ! CONFIG_KERN_IRQ
        struct sigaction sa;
        memset(&sa, 0, sizeof(sa));
 
@@ -57,6 +60,7 @@ static void timer_hw_init(void)
        sigaddset(&sa.sa_mask, SIGALRM);
        sa.sa_flags = SA_RESTART;
        sigaction(SIGALRM, &sa, NULL);
+#endif // CONFIG_KERN_IRQ
 
        // Setup POSIX realtime timer to interrupt every 1/TIMER_TICKS_PER_SEC.
        static const struct itimerval itv =
index 7c2a0c34d23cd9345c6b11a11b633f1ac551c878..0b24178db4048cb90601e4a5c641f338e86442db 100644 (file)
 #include <QtCore/QDateTime>
 #include <QtCore/QTimer>
 
+#if CONFIG_KERN_IRQ
+#include <kern/irq.h>
+#endif
+
 
 // The user interrupt server routine
 void timer_isr(void);
@@ -87,6 +91,10 @@ public:
                // Record initial time
                system_time.start();
 
+               #if CONFIG_KERN_IRQ
+                       irq_register(SIGALRM, timer_isr);
+               #endif
+
                // Activate timer interrupt
                connect(&timer, SIGNAL(timeout()), SLOT(timerInterrupt()));
                timer.start(1000 / TIMER_TICKS_PER_SEC);
@@ -116,7 +124,11 @@ public slots:
        void timerInterrupt(void)
        {
                // Just call user interrupt server, timer restarts automatically.
-               timer_isr();
+               #if CONFIG_KERN_IRQ
+                       irq_entry(SIGALRM);
+               #else
+                       timer_isr();
+               #endif
        }
 
 };
index ab3fc7a8f7db005e5f1e3f2c8623b8647a6a737e..339dc09fe089e8e00e7e38b5e77c04a412f22016 100644 (file)
@@ -26,8 +26,7 @@
  * invalidate any other reasons why the executable file might be covered by
  * the GNU General Public License.
  *
- * Copyright 2001, 2004 Develer S.r.l. (http://www.develer.com/)
- * Copyright 1999, 2000, 2001, 2008 Bernie Innocenti <bernie@codewiz.org>
+ * Copyright 2008 Bernie Innocenti <bernie@codewiz.org>
  * -->
  *
  * \brief Simple realtime multitasking scheduler.
  *
  * \version $Id: proc.c 1616 2008-08-10 19:41:26Z bernie $
  * \author Bernie Innocenti <bernie@codewiz.org>
- * \author Stefano Fedrigo <aleph@develer.com>
  */
 
 #include "proc_p.h"
 #include "proc.h"
 
 #include <cpu/frame.h> // CPU_IDLE
-
-#include <unistd.h> // XXX alarm()
+#include <drv/timer.h>
 
 
 /*
@@ -52,6 +49,8 @@
  */
 uint16_t Quantum;
 
+Timer preempt_timer;
+
 /**
  * Disable preemptive task switching.
  *
@@ -97,7 +96,7 @@ void proc_preempt(void)
        /* Poll on the ready queue for the first ready process */
        while (!(CurrentProcess = (struct Process *)list_remHead(&ProcReadyList)))
        {
-       TRACEMSG("hello2");
+       //TRACEMSG("hello2");
                /*
                 * Make sure we physically reenable interrupts here, no matter what
                 * the current task status is. This is important because if we
@@ -114,24 +113,26 @@ void proc_preempt(void)
                //FIXME: calls Qt stuff from sighandler! CPU_IDLE;
                MEMORY_BARRIER;
                IRQ_DISABLE;
-       TRACEMSG("hello3");
+       //TRACEMSG("hello3");
        }
        IRQ_ENABLE;
        TRACEMSG("hello4");
 }
 
-void proc_preempt_timer(void)
+void proc_preempt_timer(UNUSED_ARG(void *, param))
 {
-       // TODO: check Quantum
-
-       alarm(1);
-
+       IRQ_DISABLE;
        if (CurrentProcess)
        {
                TRACEMSG("preempting %p:%s", CurrentProcess, CurrentProcess->monitor.name);
-               ATOMIC(SCHED_ENQUEUE(CurrentProcess));
-               proc_schedule();
+               SCHED_ENQUEUE(CurrentProcess);
+               IRQ_ENABLE;
+               proc_preempt();
        }
+       IRQ_ENABLE;
+
+       timer_setDelay(&preempt_timer, CONFIG_KERN_QUANTUM);
+       timer_add(&preempt_timer);
 }
 
 void proc_schedule(void)
@@ -158,51 +159,60 @@ void proc_entry(void (*user_entry)(void))
 /* signal handler */
 void irq_entry(int signum)
 {
-       Process *old_process;
-
-//     TRACEMSG("storing %p:%s", CurrentProcess, CurrentProcess->monitor.name);
-//     CurrentProcess->leaving = false;
-//     getcontext(&CurrentProcess->context);
-       /* We get here in two ways: directly, and after setcontext() below */
-
-//     if (CurrentProcess->leaving)
-//     {
-//             TRACEMSG("leaving to %p:%s", CurrentProcess, CurrentProcess->monitor.name);
-//             return;
-//     }
-
-       old_process = CurrentProcess;
+       Process * const old_process = CurrentProcess;
 
        irq_handlers[signum]();
 
-       if (old_process != CurrentProcess)
+       if (!CurrentProcess)
        {
-               TRACEMSG("switching from %p:%s to %p:%s",
-                       old_process, old_process->monitor.name,
-                       CurrentProcess, CurrentProcess->monitor.name);
-               swapcontext(&old_process->context, &CurrentProcess->context);
-//             TRACEMSG("launching %p:%s", CurrentProcess, CurrentProcess->monitor.name);
-//             CurrentProcess->leaving = true;
-//             setcontext(&CurrentProcess->context);
-               /* not reached */
+               TRACEMSG("no runnable processes!");
+               IRQ_ENABLE;
+               pause();
+       }
+       else
+       {
+               if (old_process != CurrentProcess)
+               {
+                       TRACEMSG("switching from %p:%s to %p:%s",
+                               old_process, old_process ? old_process->monitor.name : "-",
+                               CurrentProcess, CurrentProcess->monitor.name);
+
+                       if (old_process)
+                               swapcontext(&old_process->context, &CurrentProcess->context);
+                       else
+                               setcontext(&CurrentProcess->context);
+
+                       /* not reached */
+               }
+               TRACEMSG("keeping %p:%s", CurrentProcess, CurrentProcess->monitor.name);
        }
+}
 
-       TRACEMSG("keeping %p:%s", CurrentProcess, CurrentProcess->monitor.name);
+void irq_register(int irq, void (*callback)(void))
+{
+       irq_handlers[irq] = callback;
 }
 
-void preempt_init(void)
+void irq_init(void)
 {
        struct sigaction act;
        act.sa_handler = irq_entry;
        sigemptyset(&act.sa_mask);
-       sigaddset(&act.sa_mask, SIGUSR1);
-       sigaddset(&act.sa_mask, SIGALRM);
+       //sigaddset(&act.sa_mask, irq);
        act.sa_flags = SA_RESTART; /* | SA_SIGINFO; */
 
-       irq_handlers[SIGUSR1] = proc_preempt;
-       irq_handlers[SIGALRM] = proc_preempt_timer;
        sigaction(SIGUSR1, &act, NULL);
-       sigaction(SIGALRM, &act, NULL);
+       #if !(ARCH & ARCH_QT)
+               sigaction(SIGALRM, &act, NULL);
+       #endif
+}
+
+void preempt_init(void)
+{
+       irq_init(); // FIXME: move before
+       irq_register(SIGUSR1, proc_preempt);
 
-       alarm(1);  // FIXME
+       timer_setSoftInt(&preempt_timer, proc_preempt_timer, NULL);
+       timer_setDelay(&preempt_timer, CONFIG_KERN_QUANTUM);
+       timer_add(&preempt_timer);
 }
index 3f2548923dbc1527660cdf3138a091c285f00aee..8692c170840fba17fad60965366d9556d7136715 100644 (file)
@@ -90,7 +90,7 @@ static void proc_init_struct(Process *proc)
        proc->sig_recv = 0;
 #endif
 
-#if CONFIG_KERN_PREEMPTIVE
+#if CONFIG_KERN_PREEMPT
        proc->forbid_cnt = 0;
 #endif
 
@@ -118,7 +118,7 @@ void proc_init(void)
        monitor_add(CurrentProcess, "main");
 #endif
 
-#if CONFIG_KERN_PREEMPTIVE
+#if CONFIG_KERN_PREEMPT
        preempt_init();
 #endif
 
index 50289a8a6adf8505defbade9ce4de7f951e2065a..00ad4a094b8fd74404aeedfbc13c8f9f0512ae60 100644 (file)
@@ -70,7 +70,7 @@ struct Process *proc_current(void);
 iptr_t proc_current_user_data(void);
 void proc_rename(struct Process *proc, const char* name);
 
-#if CONFIG_KERN_PREEMPTIVE
+#if CONFIG_KERN_PREEMPT
        void proc_forbid(void);
        void proc_permit(void);
 #else