/*#*
*#* $Log$
- *#* Revision 1.12 2004/08/25 14:12:09 rasky
- *#* Aggiornato il comment block dei log RCS
+ *#* 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.
+ *#*
+ *#* Revision 1.16 2004/10/03 20:39:28 bernie
+ *#* Import changes from sc/firmware.
+ *#*
+ *#* Revision 1.15 2004/09/20 03:29:39 bernie
+ *#* C++ fixes.
+ *#*
+ *#* Revision 1.14 2004/09/14 21:06:44 bernie
+ *#* Use debug.h instead of kdebug.h.
+ *#*
+ *#* Revision 1.13 2004/08/29 21:58:53 bernie
+ *#* Include macros.h explicityl.
*#*
*#* Revision 1.11 2004/08/24 16:09:08 bernie
*#* Add missing header.
*#*
*#*/
-#include "cpu.h"
#include "proc_p.h"
#include "proc.h"
+#include "cpu.h"
#include "event.h"
#include "hw.h"
-#include <drv/kdebug.h>
+#include <debug.h>
#include <arch_config.h> /* ARCH_EMUL */
+#include <macros.h> /* ABS() */
#include <string.h> /* memset() */
-/*! CPU dependent context switching routines
- * \note This function *MUST* preserve also the status of the interrupts.
+/*!
+ * CPU dependent context switching routines.
+ *
+ * \note This function *MUST* preserve also the status of the interrupts.
*/
-extern void asm_switch_context(cpustack_t **new_sp, cpustack_t **save_sp);
-extern int asm_switch_version(void);
+EXTERN_C void asm_switch_context(cpustack_t **new_sp, cpustack_t **save_sp);
+EXTERN_C int asm_switch_version(void);
/*
* The scheduer tracks ready and waiting processes
extern List StackFreeList;
#endif
-/* The main process (the one that executes main()) */
+/*! The main process (the one that executes main()). */
struct Process MainProcess;
-#if CONFIG_KERN_MONITOR
-List MonitorProcs;
-
-static void monitor_init(void)
-{
- INITLIST(&MonitorProcs);
-}
-
-static void monitor_add(Process* proc, const char* name, cpustack_t* stack_base, size_t stack_size)
-{
- proc->monitor.name = name;
- proc->monitor.stack_base = stack_base;
- proc->monitor.stack_size = stack_size;
-
- ADDTAIL(&MonitorProcs, &proc->monitor.link);
-}
-
-static void monitor_remove(Process* proc)
+static void proc_init_struct(Process *proc)
{
- REMOVE(&proc->monitor.link);
-}
-
-#define MONITOR_NODE_TO_PROCESS(node) \
- (struct Process*)((char*)(node) - offsetof(struct Process, monitor.link))
-
-size_t monitor_check_stack(cpustack_t* stack_base, size_t stack_size)
-{
- cpustack_t* beg;
- cpustack_t* cur;
- cpustack_t* end;
- size_t sp_free;
-
- beg = stack_base;
- end = stack_base + stack_size / sizeof(cpustack_t) - 1;
-
- if (CPU_STACK_GROWS_UPWARD)
- {
- cur = beg;
- beg = end;
- end = cur;
- }
-
- cur = beg;
- while (cur != end)
- {
- if (*cur != CONFIG_KERN_STACKFILLCODE)
- break;
-
- if (CPU_STACK_GROWS_UPWARD)
- cur--;
- else
- cur++;
- }
-
- sp_free = ABS(cur - beg) * sizeof(cpustack_t);
- return sp_free;
-}
-
-#if CONFIG_KERN_MONITOR
-
-void monitor_debug_stacks(void)
-{
- struct Process* p;
- int i;
-
- if (ISLISTEMPTY(&MonitorProcs))
- {
- kputs("No stacks registered in the monitor\n");
- return;
- }
-
- kprintf("%-24s %-6s%-8s%-8s%-8s\n", "Process name", "TCB", "SPbase", "SPsize", "SPfree");
- for (i=0;i<56;i++)
- kputchar('-');
- kputchar('\n');
-
- for (p = MONITOR_NODE_TO_PROCESS(MonitorProcs.head);
- p->monitor.link.succ;
- p = MONITOR_NODE_TO_PROCESS(p->monitor.link.succ))
- {
- size_t free = monitor_check_stack(p->monitor.stack_base, p->monitor.stack_size);
- kprintf("%-24s %04x %04x %4x %4x\n", p->monitor.name, (uint16_t)p, (uint16_t)p->monitor.stack_base, (uint16_t)p->monitor.stack_size, (uint16_t)free);
- }
-}
-
-#endif /* CONFIG_KERN_MONITOR */
-
-#endif
-
-
-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
#endif
#if (ARCH & ARCH_EMUL)
- /* Ignore stack provided by caller
- * and use the large enough default instead
- */
+ /* 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;
return proc;
}
+/*! Rename a process */
+void proc_rename(struct Process *proc, const char *name)
+{
+#if CONFIG_KERN_MONITOR
+ monitor_rename(proc, name);
+#else
+ (void)proc; (void)name;
+#endif
+}
+
/*!
* System scheduler: pass CPU control to the next process in
return CurrentProcess->user_data;
}
+
+#if CONFIG_KERN_PREEMPTIVE
+
+/*!
+ * Disable preemptive task switching.
+ *
+ * The scheduler maintains a per-process nesting counter. Task switching is
+ * effectively re-enabled only when the number of calls to proc_permit()
+ * matches the number of calls to proc_forbid().
+ *
+ * Calling functions that could sleep while task switching is disabled
+ * is dangerous, although supported. Preemptive task switching is
+ * resumed while the process is sleeping and disabled again as soon as
+ * it wakes up again.
+ *
+ * \sa proc_permit()
+ */
+void proc_forbid(void)
+{
+ /* No need to protect against interrupts here. */
+ ++CurrentProcess->forbid_cnt;
+}
+
+/*!
+ * Re-enable preemptive task switching.
+ *
+ * \sa proc_forbid()
+ */
+void proc_permit(void)
+{
+ /* No need to protect against interrupts here. */
+ --CurrentProcess->forbid_cnt;
+}
+
+#endif /* CONFIG_KERN_PREEMPTIVE */
+
+
#if 0 /* Simple testcase for the scheduler */
+#include <drv/timer.h>
+
/*!
* Proc scheduling test subthread 1
*/