This is a patch for adding the Adeos nanokernel to the Linux kernel as
described earlier:
http://marc.theaimsgroup.com/?l=linux-kernel&m=102309348817485&w=2
Here are the files added:
include/linux/adeos.h | 188 ++++++++++++
kernel/adeos.c | 712 ++++++++++++++++++++++++++++++++++++++++++++++
Here are the files modified:
include/linux/init_task.h | 51 +++
include/linux/sched.h | 4
init/Config.in | 1
init/main.c | 3
kernel/Makefile | 3
kernel/fork.c | 8
kernel/ksyms.c | 32 ++
kernel/printk.c | 114 +++++++
kernel/sched.c | 8
kernel/sysctl.c | 3
12 files changed, 1125 insertions, 2 deletions
These modifications are only aimed at making sure that Linux plays nice
with the other domains in the pipeline.
The project's web site is located here:
http://www.nongnu.org/adeos/
Any feedback is appreciated.
diff -urpN linux-2.5.38/include/linux/adeos.h linux-2.5.38-adeos/include/linux/adeos.h
--- linux-2.5.38/include/linux/adeos.h Wed Dec 31 19:00:00 1969
+++ linux-2.5.38-adeos/include/linux/adeos.h Sun Sep 22 21:57:19 2002
@@ -0,0 +1,188 @@
+/*
+ * include/linux/adeos.h
+ *
+ * Copyright (C) 2002 Philippe Gerum.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LINUX_ADEOS_H
+#define __LINUX_ADEOS_H
+
+#include <asm/adeos.h>
+
+#define ADEOS_VERSION_STRING "2.5r1c4/x86"
+
+#define ADEOS_ROOT_PRI 100
+#define ADEOS_ROOT_ID 0
+#define ADEOS_ROOT_NPTDKEYS 4 /* Must be <= 32 */
+
+#define ADEOS_OTHER_CPUS (-1)
+#define ADEOS_RESET_TIMER 0x1
+
+#define IPIPE_STALL_FLAG 0 /* Stalls a pipeline stage */
+#define IPIPE_SYNC_FLAG 1 /* IRQ sync is undergoing */
+#define IPIPE_XPEND_FLAG 2 /* Exception notification is pending */
+#define IPIPE_SLEEP_FLAG 3 /* Domain has suspended itself */
+
+#define IPIPE_HANDLE_FLAG 0
+#define IPIPE_PASS_FLAG 1
+#define IPIPE_CALLASM_FLAG 2
+#define IPIPE_ENABLE_FLAG 3
+#define IPIPE_DYNAMIC_FLAG IPIPE_HANDLE_FLAG
+#define IPIPE_EXCLUSIVE_FLAG 4
+
+#define IPIPE_HANDLE_MASK (1 << IPIPE_HANDLE_FLAG)
+#define IPIPE_PASS_MASK (1 << IPIPE_PASS_FLAG)
+#define IPIPE_CALLASM_MASK (1 << IPIPE_CALLASM_FLAG)
+#define IPIPE_ENABLE_MASK (1 << IPIPE_ENABLE_FLAG)
+#define IPIPE_DYNAMIC_MASK IPIPE_HANDLE_MASK
+#define IPIPE_EXCLUSIVE_MASK (1 << IPIPE_EXCLUSIVE_FLAG)
+
+#define IPIPE_DEFAULT_MASK (IPIPE_HANDLE_MASK|IPIPE_PASS_MASK)
+
+typedef struct adattr {
+
+ unsigned domid; /* Domain identifier -- Magic value set by caller */
+ const char *name; /* Domain name -- Warning: won't be dup'ed! */
+ int priority; /* Priority in interrupt pipeline */
+ void (*entry)(void); /* Domain entry point */
+ int estacksz; /* Stack size for entry context -- 0 means unspec */
+ void (*dswitch)(void); /* Handler called each time the domain is switched in */
+ int nptdkeys; /* Max. number of per-thread data keys */
+ void (*ptdset)(int,void *); /* Routine to set pt values */
+ void *(*ptdget)(int); /* Routine to get pt values */
+
+} adattr_t;
+
+extern adomain_t *adp_cpu_current[],
+ *adp_root;
+
+#define adp_current (adp_cpu_current[adeos_processor_id()])
+
+int adeos_register_domain(adomain_t *adp,
+ adattr_t *attr);
+
+int adeos_unregister_domain(adomain_t *adp);
+
+void adeos_renice_domain(adomain_t *adp,
+ int newpri);
+
+void adeos_suspend_domain(void);
+
+int adeos_virtualize_irq(unsigned irq,
+ void (*handler)(unsigned irq),
+ int (*acknowledge)(unsigned irq),
+ unsigned modemask);
+
+int adeos_control_irq(unsigned irq,
+ unsigned clrmask,
+ unsigned setmask);
+
+int FASTCALL(adeos_propagate_irq(unsigned irq));
+
+unsigned adeos_alloc_irq(void);
+
+int adeos_free_irq(unsigned irq);
+
+int FASTCALL(adeos_trigger_irq(unsigned irq));
+
+int FASTCALL(adeos_trigger_ipi(int cpuid));
+
+void adeos_stall_ipipe(void);
+
+static inline void adeos_stall_ipipe_from (adomain_t *adp) {
+
+ ipipe_declare_cpuid;
+ set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+}
+
+void adeos_unstall_ipipe(void);
+
+void adeos_unstall_ipipe_from(adomain_t *adp);
+
+static inline unsigned long adeos_test_ipipe_from (adomain_t *adp) {
+
+ return test_bit(IPIPE_STALL_FLAG,&adp->cpudata[adeos_processor_id()].status);
+}
+
+static inline unsigned long adeos_test_ipipe (void) {
+
+ return adeos_test_ipipe_from(adp_current);
+}
+
+static inline unsigned long adeos_test_and_stall_ipipe_from (adomain_t *adp) {
+
+ return test_and_set_bit(IPIPE_STALL_FLAG,&adp->cpudata[adeos_processor_id()].status);
+}
+
+static inline unsigned long adeos_test_and_stall_ipipe (void) {
+
+ return adeos_test_and_stall_ipipe_from(adp_current);
+}
+
+static inline void adeos_restore_ipipe_from (adomain_t *adp, unsigned long flags) {
+
+ ipipe_declare_cpuid;
+
+ if (flags)
+ set_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+ else
+ {
+ clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+ if (adp == adp_current &&
+ adp->cpudata[cpuid].irq_pending_hi != 0)
+ ipipe_sync_irqs();
+ }
+}
+
+static inline void adeos_restore_ipipe (unsigned long flags) {
+
+ adeos_restore_ipipe_from(adp_current,flags);
+}
+
+int adeos_catch_event(unsigned event,
+ void (*handler)(adevinfo_t *));
+
+static inline void adeos_propagate_event(adevinfo_t *evinfo) {
+
+ evinfo->propagate = 1;
+}
+
+void (*adeos_hook_dswitch(void (*handler)(void)))(void);
+
+void adeos_init_attr(adattr_t *attr);
+
+int adeos_get_sysinfo(adsysinfo_t *sysinfo);
+
+int adeos_tune_timer(unsigned long ns,
+ int flags);
+
+int adeos_alloc_ptdkey(void);
+
+int adeos_free_ptdkey(int key);
+
+int adeos_set_ptd(int key,
+ void *value);
+
+void *adeos_get_ptd(int key);
+
+unsigned long adeos_critical_enter(void (*syncfn)(void));
+
+void adeos_critical_exit(unsigned long flags);
+
+#endif /* !__LINUX_ADEOS_H */
diff -urpN linux-2.5.38/include/linux/init_task.h linux-2.5.38-adeos/include/linux/init_task.h
--- linux-2.5.38/include/linux/init_task.h Sun Sep 22 00:25:00 2002
+++ linux-2.5.38-adeos/include/linux/init_task.h Sun Sep 22 21:57:19 2002
@@ -54,6 +54,8 @@
* INIT_TASK is used to set up the first task table, touch at
* your own risk!. Base=0, limit=0x1fffff (=2MB)
*/
+#ifdef CONFIG_ADEOS
+
#define INIT_TASK(tsk) \
{ \
.state = 0, \
@@ -98,8 +100,57 @@
.alloc_lock = SPIN_LOCK_UNLOCKED, \
.switch_lock = SPIN_LOCK_UNLOCKED, \
.journal_info = NULL, \
+ .ptd = { [ 0 ... ADEOS_ROOT_NPTDKEYS - 1] = 0 }, \
}
+#else /* !CONFIG_ADEOS */
+
+#define INIT_TASK(tsk) \
+{ \
+ .state = 0, \
+ .thread_info = &init_thread_info, \
+ .flags = 0, \
+ .lock_depth = -1, \
+ .prio = MAX_PRIO-20, \
+ .static_prio = MAX_PRIO-20, \
+ .policy = SCHED_NORMAL, \
+ .cpus_allowed = -1, \
+ .mm = NULL, \
+ .active_mm = &init_mm, \
+ .run_list = LIST_HEAD_INIT(tsk.run_list), \
+ .time_slice = HZ, \
+ .tasks = LIST_HEAD_INIT(tsk.tasks), \
+ .ptrace_children= LIST_HEAD_INIT(tsk.ptrace_children), \
+ .ptrace_list = LIST_HEAD_INIT(tsk.ptrace_list), \
+ .real_parent = &tsk, \
+ .parent = &tsk, \
+ .children = LIST_HEAD_INIT(tsk.children), \
+ .sibling = LIST_HEAD_INIT(tsk.sibling), \
+ .group_leader = &tsk, \
+ .thread_group = LIST_HEAD_INIT(tsk.thread_group), \
+ .wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(tsk.wait_chldexit),\
+ .real_timer = { \
+ .function = it_real_fn \
+ }, \
+ .cap_effective = CAP_INIT_EFF_SET, \
+ .cap_inheritable = CAP_INIT_INH_SET, \
+ .cap_permitted = CAP_FULL_SET, \
+ .keep_capabilities = 0, \
+ .rlim = INIT_RLIMITS, \
+ .user = INIT_USER, \
+ .comm = "swapper", \
+ .thread = INIT_THREAD, \
+ .fs = &init_fs, \
+ .files = &init_files, \
+ .sigmask_lock = SPIN_LOCK_UNLOCKED, \
+ .sig = &init_signals, \
+ .pending = { NULL, &tsk.pending.head, {{0}}}, \
+ .blocked = {{0}}, \
+ .alloc_lock = SPIN_LOCK_UNLOCKED, \
+ .switch_lock = SPIN_LOCK_UNLOCKED, \
+ .journal_info = NULL, \
+}
+#endif /* CONFIG_ADEOS */
#endif
diff -urpN linux-2.5.38/include/linux/sched.h linux-2.5.38-adeos/include/linux/sched.h
--- linux-2.5.38/include/linux/sched.h Sun Sep 22 00:25:00 2002
+++ linux-2.5.38-adeos/include/linux/sched.h Sun Sep 22 21:57:19 2002
@@ -398,6 +398,10 @@ struct task_struct {
/* journalling filesystem info */
void *journal_info;
struct dentry *proc_dentry;
+
+#ifdef CONFIG_ADEOS
+ void *ptd[ADEOS_ROOT_NPTDKEYS];
+#endif /* CONFIG_ADEOS */
};
extern void __put_task_struct(struct task_struct *tsk);
diff -urpN linux-2.5.38/init/Config.in linux-2.5.38-adeos/init/Config.in
--- linux-2.5.38/init/Config.in Sun Sep 22 00:25:01 2002
+++ linux-2.5.38-adeos/init/Config.in Sun Sep 22 21:57:19 2002
@@ -5,6 +5,7 @@ endmenu
mainmenu_option next_comment
comment 'General setup'
+bool 'Adaptive Domain Environment support' CONFIG_ADEOS
bool 'Networking support' CONFIG_NET
bool 'System V IPC' CONFIG_SYSVIPC
bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
diff -urpN linux-2.5.38/init/main.c linux-2.5.38-adeos/init/main.c
--- linux-2.5.38/init/main.c Sun Sep 22 00:25:02 2002
+++ linux-2.5.38-adeos/init/main.c Sun Sep 22 21:57:19 2002
@@ -396,6 +396,9 @@ asmlinkage void __init start_kernel(void
build_all_zonelists();
printk("Kernel command line: %s\n", saved_command_line);
parse_options(command_line);
+#ifdef CONFIG_ADEOS
+ __adeos_init();
+#endif /* CONFIG_ADEOS */
trap_init();
init_IRQ();
sched_init();
diff -urpN linux-2.5.38/kernel/Makefile linux-2.5.38-adeos/kernel/Makefile
--- linux-2.5.38/kernel/Makefile Sun Sep 22 00:25:03 2002
+++ linux-2.5.38-adeos/kernel/Makefile Sun Sep 22 21:57:19 2002
@@ -3,7 +3,7 @@
#
export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
- printk.o platform.o suspend.o dma.o
+ printk.o platform.o suspend.o dma.o adeos.o
obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
module.o exit.o itimer.o time.o softirq.o resource.o \
@@ -17,6 +17,7 @@ obj-$(CONFIG_MODULES) += ksyms.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o
+obj-$(CONFIG_ADEOS) += adeos.o
ifneq ($(CONFIG_IA64),y)
# According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
diff -urpN linux-2.5.38/kernel/adeos.c linux-2.5.38-adeos/kernel/adeos.c
--- linux-2.5.38/kernel/adeos.c Wed Dec 31 19:00:00 1969
+++ linux-2.5.38-adeos/kernel/adeos.c Sun Sep 22 21:57:19 2002
@@ -0,0 +1,712 @@
+/*
+ * linux/kernel/adeos.c
+ *
+ * Copyright (C) 2002 Philippe Gerum.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * This code implements the architecture-independent ADEOS support.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <asm/system.h>
+
+/* The pre-defined domain slot for the root domain. */
+static adomain_t adeos_root_domain;
+
+/* A constant pointer to the root domain. */
+adomain_t *adp_root = &adeos_root_domain;
+
+/* A pointer to the current domain. */
+adomain_t *adp_cpu_current[ADEOS_NR_CPUS] = { [ 0 ... ADEOS_NR_CPUS - 1] = &adeos_root_domain };
+
+/* The spinlock protecting from races while modifying the pipeline. */
+spinlock_t adeos_pipelock = SPIN_LOCK_UNLOCKED;
+
+/* The pipeline data structure. Enqueues adomain_t objects by priority. */
+struct list_head adeos_pipeline;
+
+/* An array of global counters tracking domains monitoring events. */
+int __adeos_event_monitors[ADEOS_NR_EVENTS] = { [ 0 ... ADEOS_NR_EVENTS - 1] = 0 };
+
+/* Number of on-line CPUS. */
+int __adeos_online_cpus = 1;
+
+/* adeos_init() -- Initialization routine of the ADEOS layer. Called
+ by the host kernel early during the boot procedure. */
+
+void __adeos_init (void)
+
+{
+ adattr_t attr;
+
+ printk("ADEOS %s enabled.\n",ADEOS_VERSION_STRING);
+
+ INIT_LIST_HEAD(&adeos_pipeline);
+ __adeos_online_cpus = smp_num_cpus;
+
+ attr.domid = ADEOS_ROOT_ID;
+ attr.name = "Linux";
+ attr.entry = NULL;
+ attr.priority = ADEOS_ROOT_PRI;
+ attr.estacksz = 0; /* Unused. */
+ attr.dswitch = NULL;
+ attr.nptdkeys = ADEOS_ROOT_NPTDKEYS;
+ attr.ptdset = &__adeos_set_root_ptd;
+ attr.ptdget = &__adeos_get_root_ptd;
+
+ adeos_register_domain(&adeos_root_domain,&attr);
+}
+
+#ifdef CONFIG_PROC_FS
+
+#include <linux/proc_fs.h>
+
+static struct proc_dir_entry *adeos_proc_entry;
+
+static int __adeos_read_proc (char *page,
+ char **start,
+ off_t off,
+ int count,
+ int *eof,
+ void *data)
+{
+ struct list_head *pos;
+ unsigned long flags;
+ char *p = page;
+ int len;
+
+ p += sprintf(p,"Prio\tID\t\tDomain\n\n");
+
+ ipipe_hw_save_flags_and_cli(flags);
+
+ list_for_each(pos,&adeos_pipeline) {
+ adomain_t *adp = list_entry(pos,adomain_t,link);
+ p += sprintf(p," %d\t0x%.8x\t%s\n",
+ adp->priority,
+ adp->domid,
+ adp->name);
+ }
+
+ ipipe_hw_restore_flags(flags);
+
+ len = p - page;
+
+ if (len <= off + count)
+ *eof = 1;
+
+ *start = page + off;
+
+ len -= off;
+
+ if (len > count)
+ len = count;
+
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+
+void __adeos_init_proc (void) {
+
+ adeos_proc_entry = create_proc_read_entry("adeos",
+ 0444,
+ NULL,
+ &__adeos_read_proc,
+ NULL);
+}
+
+#endif /* CONFIG_PROC_FS */
+
+/* adeos_register_domain() -- Add a new domain to the system. All
+ client domains must call this routine to register themselves to
+ ADEOS before using its services. */
+
+int adeos_register_domain (adomain_t *adp, adattr_t *attr)
+
+{
+ struct list_head *pos;
+ unsigned long flags;
+ ipipe_declare_cpuid;
+ int n;
+
+ if (adp_current != adp_root)
+ {
+ printk(KERN_WARNING "ADEOS: Only the root domain may register a new domain.\n");
+ return -EPERM;
+ }
+
+ for (n = 0; n < ADEOS_NR_CPUS; n++)
+ {
+ adp->cpudata[n].status = 0;
+
+ /* A special case for domains who won't process events. We
+ need to act as if they had suspended themselves. */
+
+ if (attr->entry == NULL && adp != adp_root)
+ set_bit(IPIPE_SLEEP_FLAG,&adp->cpudata[n].status);
+ }
+
+ /* A special case for domains who won't process events (i.e. no
+ entry). We have to mark them as suspended so that
+ adeos_suspend_domain() won't consider them, unless they
+ _actually_ receive events, which would lead to a panic
+ situation since they have no stack context... :o> */
+
+ if (attr->entry == NULL && adp != adp_root)
+ for (n = 0; n < ADEOS_NR_CPUS; n++)
+ set_bit(IPIPE_SLEEP_FLAG,&adp->cpudata[n].status);
+
+ adp->name = attr->name;
+ adp->priority = attr->priority;
+ adp->domid = attr->domid;
+ adp->dswitch = attr->dswitch;
+ adp->ptd_setfun = attr->ptdset;
+ adp->ptd_getfun = attr->ptdget;
+ adp->ptd_keymap = 0;
+ adp->ptd_keycount = 0;
+ adp->ptd_keymax = attr->nptdkeys;
+
+ for (n = 0; n < ADEOS_NR_EVENTS; n++)
+ /* Event handlers must be cleared before the i-pipe stage is
+ inserted since an exception may occur on behalf of the new
+ emerging domain. */
+ adp->events[n].handler = NULL;
+
+ if (attr->entry != NULL)
+ __adeos_bootstrap_domain(adp,attr);
+
+ printk("ADEOS: Domain %s registered.\n",adp->name);
+
+ /* Insert the domain in the interrupt pipeline last, so it won't
+ be resumed for processing interrupts until it has a valid stack
+ context. */
+
+ ipipe_init_stage(adp);
+
+ INIT_LIST_HEAD(&adp->link);
+
+ flags = __adeos_critical_enter(NULL);
+
+ list_for_each(pos,&adeos_pipeline) {
+ adomain_t *_adp = list_entry(pos,adomain_t,link);
+ if (adp->priority > _adp->priority)
+ break;
+ }
+
+ list_add_tail(&adp->link,pos);
+
+ __adeos_critical_exit(flags);
+
+ /* Finally, allow the new domain to perform its initialization
+ chores on behalf of its own stack context. */
+
+ if (attr->entry != NULL)
+ {
+ __adeos_switch_domain(adp);
+
+ ipipe_reload_cpuid(); /* Processor might have changed. */
+
+ if (!test_bit(IPIPE_STALL_FLAG,&adp_root->cpudata[cpuid].status) &&
+ adp_root->cpudata[cpuid].irq_pending_hi != 0)
+ ipipe_sync_irqs();
+ }
+
+ return 0;
+}
+
+/* adeos_unregister_domain() -- Remove a domain from the system. All
+ client domains must call this routine to unregister themselves from
+ the ADEOS layer. */
+
+int adeos_unregister_domain (adomain_t *adp)
+
+{
+ unsigned long flags;
+ unsigned event;
+
+ if (adp_current != adp_root)
+ {
+ printk(KERN_WARNING "ADEOS: Only the root domain may unregister a domain.\n");
+ return -EPERM;
+ }
+
+ if (adp == adp_root)
+ {
+ printk(KERN_WARNING "ADEOS: Cannot unregister the root domain.\n");
+ return -EPERM;
+ }
+
+ for (event = 0; event < ADEOS_NR_EVENTS; event++)
+ /* Need this to update the monitor count. */
+ adeos_catch_event(event,NULL);
+
+ /* Simply remove the domain from the pipeline and we are almost
+ done. */
+
+ flags = __adeos_critical_enter(NULL);
+ list_del_init(&adp->link);
+ __adeos_critical_exit(flags);
+
+ __adeos_cleanup_domain(adp);
+
+ printk("ADEOS: Domain %s unregistered.\n",adp->name);
+
+ return 0;
+}
+
+/* adeos_renice_domain() -- Change a domain's priority. This affects
+ the position of the domain in the interrupt pipeline. The greater
+ the priority value, the earlier the domain is informed of incoming
+ events when the pipeline is processed. */
+
+void adeos_renice_domain (adomain_t *adp, int newpri)
+
+{
+ struct list_head *pos;
+ unsigned long flags;
+
+ /* Allows round-robin effect if newpri == oldpri. */
+
+ flags = __adeos_critical_enter(NULL);
+
+ list_del_init(&adp->link);
+
+ list_for_each(pos,&adeos_pipeline) {
+ adomain_t *_adp = list_entry(pos,adomain_t,link);
+ if (newpri > _adp->priority)
+ break;
+ }
+
+ list_add_tail(&adp->link,pos);
+ adp->priority = newpri;
+
+ __adeos_critical_exit(flags);
+}
+
+/* adeos_suspend_domain() -- tell the ADEOS layer that the current
+ domain is now dormant. The calling domain is switched out, while
+ the next domain with work in progress or pending in the pipeline is
+ switched in. */
+
+void adeos_suspend_domain (void)
+
+{
+ struct adcpudata *cpudata;
+ adomain_t *adp, *nadp;
+ struct list_head *ln;
+ unsigned long flags;
+ ipipe_declare_cpuid;
+
+ adp = nadp = adp_cpu_current[cpuid];
+ cpudata = &adp->cpudata[cpuid];
+
+ ipipe_hw_local_irq_save(flags);
+
+ for (;;)
+ {
+ ln = nadp->link.next;
+
+ if (ln == &adeos_pipeline) /* End of pipeline reached? */
+ {
+ /* Caller should loop on its idle task on return. */
+ ipipe_hw_local_irq_restore(flags);
+
+ if (test_and_clear_bit(IPIPE_STALL_FLAG,&cpudata->status) &&
+ cpudata->irq_pending_hi != 0)
+ ipipe_sync_irqs();
+
+ return;
+ }
+
+ nadp = list_entry(ln,adomain_t,link);
+
+ /* Make sure the domain was preempted (i.e. not sleeping) or
+ has some event to process before switching to it. */
+
+ if (!test_bit(IPIPE_SLEEP_FLAG,&nadp->cpudata[cpuid].status) ||
+ nadp->cpudata[cpuid].irq_pending_hi != 0 ||
+ test_bit(IPIPE_XPEND_FLAG,&nadp->cpudata[cpuid].status))
+ break;
+ }
+
+ /* A suspending domain implicitely unstalls the pipeline. */
+ clear_bit(IPIPE_STALL_FLAG,&cpudata->status);
+
+ /* Mark the outgoing domain as aslept (i.e. not preempted). */
+ set_bit(IPIPE_SLEEP_FLAG,&cpudata->status);
+
+ /* Conversely, clear the sleep bit for the incoming domain. */
+ clear_bit(IPIPE_SLEEP_FLAG,&nadp->cpudata[cpuid].status);
+
+ /* Suspend the calling domain, switching to the next one. */
+ __adeos_switch_domain(nadp);
+
+ ipipe_hw_local_irq_restore(flags);
+
+#ifdef CONFIG_SMP
+ ipipe_reload_cpuid(); /* Processor might have changed. */
+ adp = adp_cpu_current[cpuid];
+ cpudata = &adp->cpudata[cpuid];
+#endif
+
+ /* Now, we are back into the calling domain. Flush the interrupt
+ log and fire the event interposition handler if needed. */
+
+ if (cpudata->irq_pending_hi != 0)
+ ipipe_sync_irqs();
+
+ /* Caution: CPU migration is allowed in SMP-mode on behalf of an
+ event handler provided that the current domain raised
+ it. Otherwise, it's not. */
+
+ if (test_and_clear_bit(IPIPE_XPEND_FLAG,&cpudata->status))
+ adp->events[cpudata->event_data.event].handler(&cpudata->event_data);
+
+ /* Return to the point of suspension in the calling domain. */
+}
+
+/* adeos_virtualize_irq() -- Attach a handler (and optionally an hw
+ acknowledge routine) to an interrupt for the current domain. */
+
+int adeos_virtualize_irq (unsigned irq,
+ void (*handler)(unsigned irq),
+ int (*acknowledge)(unsigned irq),
+ unsigned modemask)
+{
+ if (irq >= IPIPE_NR_IRQS)
+ return -EINVAL;
+
+ return ipipe_hook_irq(irq,handler,acknowledge,modemask);
+}
+
+/* adeos_control_irq() -- Change an interrupt mode. This affects the
+ way a given interrupt is handled by ADEOS for the current
+ domain. setmask is a bitmask telling whether:
+ - the interrupt should be passed to the domain (IPIPE_HANDLE_MASK),
+ and/or
+ - the interrupt should be passed down to the lower priority domain(s)
+ in the pipeline (IPIPE_PASS_MASK).
+ This leads to four possibilities:
+ - PASS only => Ignore the interrupt
+ - HANDLE only => Terminate the interrupt (process but don't pass down)
+ - PASS + HANDLE => Accept the interrupt (process and pass down)
+ - <none> => Discard the interrupt
+ - DYNAMIC is currently an alias of HANDLE since it marks an interrupt
+ which is processed by the current domain but not implicitely passed
+ down to the pipeline, letting the domain's handler choose on a case-
+ by-case basis whether the interrupt propagation should be forced
+ using adeos_propagate_irq().
+ clrmask clears the corresponding bits from the control field before
+ setmask is applied.
+*/
+
+int adeos_control_irq (unsigned irq,
+ unsigned clrmask,
+ unsigned setmask) {
+
+ if (irq >= IPIPE_NR_IRQS)
+ return -EINVAL;
+
+ return ipipe_control_irq(irq,clrmask,setmask);
+}
+
+/* adeos_propagate_irq() -- Force a given IRQ propagation on behalf of
+ a running interrupt handler to the next domain down the pipeline.
+ Returns non-zero if a domain has received the interrupt
+ notification, zero otherwise.
+ This call is useful for handling shared interrupts among domains.
+ e.g. pipeline = [domain-A]---[domain-B]...
+ Both domains share IRQ #X.
+ - domain-A handles IRQ #X but does not pass it down (i.e. Terminate
+ or Dynamic interrupt control mode)
+ - domain-B handles IRQ #X (i.e. Terminate or Accept interrupt
+ control modes).
+ When IRQ #X is raised, domain-A's handler determines whether it
+ should process the interrupt by identifying its source. If not,
+ adeos_propagate_irq() is called so that the next domain down the
+ pipeline which handles IRQ #X is given a chance to process it. This
+ process can be repeated until the end of the pipeline is
+ reached. */
+
+int adeos_propagate_irq (unsigned irq) {
+
+ return irq < IPIPE_NR_IRQS ? ipipe_propagate_irq(irq) : -EINVAL;
+}
+
+/* adeos_alloc_irq() -- Allocate a virtual/soft pipelined interrupt.
+ Virtual interrupts are handled in exactly the same way than their
+ hw-generated counterparts. This is a very basic, one-way only,
+ inter-domain communication system (see adeos_trigger_irq()). Note:
+ it is not necessary for a domain to allocate a virtual interrupt to
+ trap it using adeos_virtualize_irq(). The newly allocated VIRQ
+ number which can be passed to other IRQ-related services is
+ returned on success, zero otherwise (i.e. no more virtual interrupt
+ channel is available). */
+
+unsigned adeos_alloc_irq (void) {
+
+ return ipipe_alloc_irq();
+}
+
+/* adeos_free_irq() -- Return a previously allocated virtual/soft
+ pipelined interrupt to the pool of allocatable interrupts. */
+
+int adeos_free_irq (unsigned irq)
+
+{
+ if (irq >= IPIPE_NR_IRQS)
+ return -EINVAL;
+
+ ipipe_free_irq(irq);
+
+ return 0;
+}
+
+/* adeos_trigger_irq() -- Push the interrupt to the pipeline entry
+ just like if it has been actually received from a hw source. This
+ both works for real and virtual interrupts. This also means that
+ the current domain might be immediately preempted by a more
+ prioritary domain who happens to handle this interrupt. */
+
+int adeos_trigger_irq (unsigned irq) {
+
+ return irq < IPIPE_NR_IRQS ? ipipe_trigger_irq(irq) : -EINVAL;
+}
+
+/* adeos_trigger_ipi() -- Send the ADEOS service IPI to other
+ processors. This leads to */
+
+int adeos_trigger_ipi (int cpuid) {
+
+ return ipipe_trigger_ipi(cpuid);
+}
+
+int adeos_get_sysinfo (adsysinfo_t *info) {
+
+ return __adeos_get_sysinfo(info);
+}
+
+/* adeos_stall_ipipe() -- Stall the interrupt pipeline. Must be
+ callable from C and assembly language. */
+
+void adeos_stall_ipipe (void) {
+
+ ipipe_declare_cpuid;
+
+ set_bit(IPIPE_STALL_FLAG,&adp_current->cpudata[cpuid].status);
+}
+
+/* adeos_unstall_ipipe() -- Unstall the interrupt pipeline and
+ synchronize pending events. Must be callable from C and assembly
+ language. */
+
+void adeos_unstall_ipipe (void)
+
+{
+ ipipe_declare_cpuid;
+
+ clear_bit(IPIPE_STALL_FLAG,&adp_current->cpudata[cpuid].status);
+ ipipe_hw_sti();
+
+ if (adp_current->cpudata[cpuid].irq_pending_hi != 0)
+ ipipe_sync_irqs();
+}
+
+/* adeos_unstall_ipipe() -- Unstall the interrupt pipeline and
+ synchronize pending events from a given domain. */
+
+void adeos_unstall_ipipe_from (adomain_t *adp)
+
+{
+ struct list_head *pos;
+ ipipe_declare_cpuid;
+
+ clear_bit(IPIPE_STALL_FLAG,&adp->cpudata[cpuid].status);
+
+ if (adp == adp_cpu_current[cpuid])
+ {
+ ipipe_hw_sti();
+
+ if (adp->cpudata[cpuid].irq_pending_hi != 0)
+ ipipe_sync_irqs();
+
+ return;
+ }
+
+ /* Attempt to flush all events that might be pending at the
+ unstalled domain level. This code is roughly lifted from
+ ipipe.c:ipipe_handle_irq(). */
+
+ list_for_each(pos,&adeos_pipeline) {
+
+ adomain_t *_adp = list_entry(pos,adomain_t,link);
+
+ if (test_bit(IPIPE_STALL_FLAG,&_adp->cpudata[cpuid].status))
+ break; /* Stalled stage -- do not go further. */
+
+ if (_adp->cpudata[cpuid].irq_pending_hi != 0)
+ {
+ /* Since the critical IPI might be serviced by the
+ following actions, the current domain might not be
+ linked to the pipeline anymore after its handler
+ returns on SMP boxes, even if the domain remains valid
+ (see adeos_unregister_domain()), so don't make any
+ hazardous assumptions here. */
+
+ ipipe_hw_sti();
+
+ if (_adp == adp_cpu_current[cpuid])
+ ipipe_sync_irqs();
+ else
+ {
+ __adeos_switch_domain(_adp);
+ ipipe_reload_cpuid(); /* Processor might have changed. */
+ }
+
+ break;
+ }
+ else if (_adp == adp_cpu_current[cpuid])
+ break;
+ }
+}
+
+/* adeos_catch_event() -- Interpose an event handler for the
+ current domain. */
+
+int adeos_catch_event (unsigned event, void (*handler)(adevinfo_t *))
+
+{
+ if (event >= ADEOS_NR_EVENTS)
+ return -EINVAL;
+
+ if (!xchg(&adp_current->events[event].handler,handler))
+ {
+ if (handler)
+ __adeos_event_monitors[event]++;
+ }
+ else if (!handler)
+ __adeos_event_monitors[event]--;
+
+ return 0;
+}
+
+void (*adeos_hook_dswitch(void (*handler)(void))) (void) {
+
+ return (void (*)(void))xchg(&adp_current->dswitch,handler);
+}
+
+void adeos_init_attr (adattr_t *attr)
+
+{
+ attr->name = "Anonymous";
+ attr->domid = 1;
+ attr->entry = NULL;
+ attr->estacksz = 0; /* Let ADEOS choose a reasonable stack size */
+ attr->priority = ADEOS_ROOT_PRI;
+ attr->dswitch = NULL;
+ attr->nptdkeys = 0;
+ attr->ptdset = NULL;
+ attr->ptdget = NULL;
+}
+
+int adeos_tune_timer (unsigned long ns, int flags) {
+
+ return __adeos_tune_timer(ns,flags);
+}
+
+int adeos_alloc_ptdkey (void)
+
+{
+ unsigned long flags;
+ int key = -1;
+
+ ipipe_hw_spin_lock(&adeos_pipelock,flags);
+
+ if (adp_current->ptd_keycount < adp_current->ptd_keymax)
+ {
+ key = ffz(adp_current->ptd_keymap);
+ set_bit(key,&adp_current->ptd_keymap);
+ adp_current->ptd_keycount++;
+ }
+
+ ipipe_hw_spin_unlock(&adeos_pipelock,flags);
+
+ return key;
+}
+
+int adeos_free_ptdkey (int key)
+
+{
+ unsigned long flags;
+
+ if (key < 0 || key >= adp_current->ptd_keymax)
+ return -EINVAL;
+
+ ipipe_hw_spin_lock(&adeos_pipelock,flags);
+
+ if (test_and_clear_bit(key,&adp_current->ptd_keymap))
+ adp_current->ptd_keycount--;
+
+ ipipe_hw_spin_unlock(&adeos_pipelock,flags);
+
+ return 0;
+}
+
+int adeos_set_ptd (int key, void *value)
+
+{
+ if (key < 0 || key >= adp_current->ptd_keymax)
+ return -EINVAL;
+
+ if (!adp_current->ptd_setfun)
+ {
+ printk(KERN_WARNING "ADEOS: not ptdset hook for %s\n",adp_current->name);
+ return -EINVAL;
+ }
+
+ adp_current->ptd_setfun(key,value);
+
+ return 0;
+}
+
+void *adeos_get_ptd (int key)
+
+{
+ if (key < 0 || key >= adp_current->ptd_keymax)
+ return NULL;
+
+ if (!adp_current->ptd_getfun)
+ {
+ printk(KERN_WARNING "ADEOS: not ptdget hook for %s\n",adp_current->name);
+ return NULL;
+ }
+
+ return adp_current->ptd_getfun(key);
+}
+
+unsigned long adeos_critical_enter (void (*syncfn)(void)) {
+
+ return __adeos_critical_enter(syncfn);
+}
+
+void adeos_critical_exit (unsigned long flags) {
+
+ __adeos_critical_exit(flags);
+}
diff -urpN linux-2.5.38/kernel/fork.c linux-2.5.38-adeos/kernel/fork.c
--- linux-2.5.38/kernel/fork.c Sun Sep 22 00:25:00 2002
+++ linux-2.5.38-adeos/kernel/fork.c Sun Sep 22 21:57:19 2002
@@ -846,6 +846,14 @@ static struct task_struct *copy_process(
nr_threads++;
write_unlock_irq(&tasklist_lock);
+#ifdef CONFIG_ADEOS
+ {
+ int k;
+
+ for (k = 0; k < ADEOS_ROOT_NPTDKEYS; k++)
+ p->ptd[k] = NULL;
+ }
+#endif /* CONFIG_ADEOS */
retval = 0;
fork_out:
diff -urpN linux-2.5.38/kernel/ksyms.c linux-2.5.38-adeos/kernel/ksyms.c
--- linux-2.5.38/kernel/ksyms.c Sun Sep 22 00:24:58 2002
+++ linux-2.5.38-adeos/kernel/ksyms.c Sun Sep 22 21:57:19 2002
@@ -612,3 +612,35 @@ EXPORT_SYMBOL(__per_cpu_offset);
/* debug */
EXPORT_SYMBOL(dump_stack);
+
+#ifdef CONFIG_ADEOS
+EXPORT_SYMBOL(adeos_register_domain);
+EXPORT_SYMBOL(adeos_unregister_domain);
+EXPORT_SYMBOL(adeos_renice_domain);
+EXPORT_SYMBOL(adeos_suspend_domain);
+EXPORT_SYMBOL(adeos_virtualize_irq);
+EXPORT_SYMBOL(adeos_control_irq);
+EXPORT_SYMBOL(adeos_propagate_irq);
+EXPORT_SYMBOL(adeos_alloc_irq);
+EXPORT_SYMBOL(adeos_free_irq);
+EXPORT_SYMBOL(adeos_trigger_irq);
+EXPORT_SYMBOL(adeos_trigger_ipi);
+EXPORT_SYMBOL(adeos_stall_ipipe);
+EXPORT_SYMBOL(adeos_unstall_ipipe);
+EXPORT_SYMBOL(adeos_unstall_ipipe_from);
+EXPORT_SYMBOL(adeos_catch_event);
+EXPORT_SYMBOL(adeos_hook_dswitch);
+EXPORT_SYMBOL(adeos_init_attr);
+EXPORT_SYMBOL(adeos_get_sysinfo);
+EXPORT_SYMBOL(adeos_tune_timer);
+EXPORT_SYMBOL(adeos_alloc_ptdkey);
+EXPORT_SYMBOL(adeos_free_ptdkey);
+EXPORT_SYMBOL(adeos_set_ptd);
+EXPORT_SYMBOL(adeos_get_ptd);
+EXPORT_SYMBOL(adeos_critical_enter);
+EXPORT_SYMBOL(adeos_critical_exit);
+EXPORT_SYMBOL(adp_cpu_current);
+EXPORT_SYMBOL(adp_root);
+/* Private symbols. */
+EXPORT_SYMBOL(__adeos_online_cpus);
+#endif /* CONFIG_ADEOS */
diff -urpN linux-2.5.38/kernel/printk.c linux-2.5.38-adeos/kernel/printk.c
--- linux-2.5.38/kernel/printk.c Sun Sep 22 00:25:31 2002
+++ linux-2.5.38-adeos/kernel/printk.c Sun Sep 22 21:57:19 2002
@@ -194,17 +194,33 @@ int do_syslog(int type, char * buf, int
if (error)
goto out;
i = 0;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_disable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
while ((log_start != log_end) && i < len) {
c = LOG_BUF(log_start);
log_start++;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock_enable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_unlock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
__put_user(c,buf);
buf++;
i++;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_disable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
}
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock_enable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_unlock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
error = i;
break;
case 4: /* Read/clear last kernel messages */
@@ -223,7 +239,11 @@ int do_syslog(int type, char * buf, int
count = len;
if (count > LOG_BUF_LEN)
count = LOG_BUF_LEN;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_disable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
if (count > logged_chars)
count = logged_chars;
if (do_clear)
@@ -240,11 +260,23 @@ int do_syslog(int type, char * buf, int
if (j+LOG_BUF_LEN < log_end)
break;
c = LOG_BUF(j);
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock_enable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_unlock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
__put_user(c,&buf[count-1-i]);
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_disable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
}
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock_enable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_unlock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
error = i;
if(i != count) {
int offset = count-error;
@@ -257,19 +289,43 @@ int do_syslog(int type, char * buf, int
break;
case 5: /* Clear ring buffer */
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_disable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
logged_chars = 0;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock_enable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_unlock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
break;
case 6: /* Disable logging to console */
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_disable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
console_loglevel = minimum_console_loglevel;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock_enable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_unlock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
break;
case 7: /* Enable logging to console */
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_disable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
console_loglevel = default_console_loglevel;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock_enable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_unlock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
break;
case 8: /* Set level of messages printed to console */
error = -EINVAL;
@@ -277,15 +333,31 @@ int do_syslog(int type, char * buf, int
goto out;
if (len < minimum_console_loglevel)
len = minimum_console_loglevel;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_disable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
console_loglevel = len;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock_enable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_unlock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
error = 0;
break;
case 9: /* Number of chars in the log buffer */
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_disable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
error = log_end - log_start;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock_enable(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_unlock_irq(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
break;
case 10:
lbuf = kmalloc(len + 1, GFP_KERNEL);
@@ -430,13 +502,21 @@ asmlinkage int printk(const char *fmt, .
if (oops_in_progress) {
/* If a crash is occurring, make sure we can't deadlock */
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock_init(&logbuf_lock);
+#else /* !CONFIG_ADEOS */
spin_lock_init(&logbuf_lock);
+#endif /* CONFIG_ADEOS */
/* And make sure that we print immediately */
init_MUTEX(&console_sem);
}
/* This stops the holder of console_sem just where we want him */
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock(&logbuf_lock, flags);
+#else /* !CONFIG_ADEOS */
spin_lock_irqsave(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS */
/* Emit the output into the temporary buffer */
va_start(args, fmt);
@@ -466,7 +546,11 @@ asmlinkage int printk(const char *fmt, .
* On some architectures, the consoles are not usable
* on secondary CPUs early in the boot process.
*/
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock(&logbuf_lock, flags);
+#else /* !CONFIG_ADEOS */
spin_unlock_irqrestore(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS */
goto out;
}
if (!down_trylock(&console_sem)) {
@@ -474,7 +558,11 @@ asmlinkage int printk(const char *fmt, .
* We own the drivers. We can drop the spinlock and let
* release_console_sem() print the text
*/
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock(&logbuf_lock, flags);
+#else /* !CONFIG_ADEOS */
spin_unlock_irqrestore(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS */
console_may_schedule = 0;
release_console_sem();
} else {
@@ -483,7 +571,11 @@ asmlinkage int printk(const char *fmt, .
* allows the semaphore holder to proceed and to call the
* console drivers with the output which we just produced.
*/
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock(&logbuf_lock, flags);
+#else /* !CONFIG_ADEOS */
spin_unlock_irqrestore(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS */
}
out:
return printed_len;
@@ -528,19 +620,31 @@ void release_console_sem(void)
unsigned long wake_klogd = 0;
for ( ; ; ) {
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock(&logbuf_lock, flags);
+#else /* !CONFIG_ADEOS */
spin_lock_irqsave(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS */
wake_klogd |= log_start - log_end;
if (con_start == log_end)
break; /* Nothing to print */
_con_start = con_start;
_log_end = log_end;
con_start = log_end; /* Flush */
- spin_unlock_irqrestore(&logbuf_lock, flags);
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock(&logbuf_lock, flags);
+#else /* !CONFIG_ADEOS */
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS */
call_console_drivers(_con_start, _log_end);
}
console_may_schedule = 0;
up(&console_sem);
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock(&logbuf_lock, flags);
+#else /* !CONFIG_ADEOS */
spin_unlock_irqrestore(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS */
if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait))
wake_up_interruptible(&log_wait);
}
@@ -653,9 +757,17 @@ void register_console(struct console * c
/*
* release_cosole_sem() will print out the buffered messages for us.
*/
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_lock(&logbuf_lock, flags);
+#else /* !CONFIG_ADEOS */
spin_lock_irqsave(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS */
con_start = log_start;
+#ifdef CONFIG_ADEOS
+ ipipe_hw_spin_unlock(&logbuf_lock, flags);
+#else /* !CONFIG_ADEOS */
spin_unlock_irqrestore(&logbuf_lock, flags);
+#endif /* CONFIG_ADEOS */
}
release_console_sem();
}
diff -urpN linux-2.5.38/kernel/sched.c linux-2.5.38-adeos/kernel/sched.c
--- linux-2.5.38/kernel/sched.c Sun Sep 22 00:25:17 2002
+++ linux-2.5.38-adeos/kernel/sched.c Sun Sep 22 21:57:19 2002
@@ -1041,6 +1041,14 @@ asmlinkage void preempt_schedule(void)
{
struct thread_info *ti = current_thread_info();
+#ifdef CONFIG_ADEOS
+ /* The in-kernel preemption routine might be indirectly called
+ from code running in other domains, so we must ensure that
+ scheduling only takes place on behalf of the root (Linux)
+ one. */
+ if (adp_current != adp_root)
+ return;
+#endif /* CONFIG_ADEOS */
/*
* If there is a non-zero preempt_count or interrupts are disabled,
* we do not want to preempt the current task. Just return..
diff -urpN linux-2.5.38/kernel/sysctl.c linux-2.5.38-adeos/kernel/sysctl.c
--- linux-2.5.38/kernel/sysctl.c Sun Sep 22 00:25:00 2002
+++ linux-2.5.38-adeos/kernel/sysctl.c Sun Sep 22 21:57:19 2002
@@ -362,6 +362,9 @@ void __init sysctl_init(void)
#ifdef CONFIG_PROC_FS
register_proc_table(root_table, proc_sys_root);
init_irq_proc();
+#ifdef CONFIG_ADEOS
+ __adeos_init_proc();
+#endif /* CONFIG_ADEOS */
#endif
}
Em Sun, Sep 22, 2002 at 10:58:57PM -0400, Karim Yaghmour escreveu:
> diff -urpN linux-2.5.38/kernel/printk.c linux-2.5.38-adeos/kernel/printk.c
> --- linux-2.5.38/kernel/printk.c Sun Sep 22 00:25:31 2002
> +++ linux-2.5.38-adeos/kernel/printk.c Sun Sep 22 21:57:19 2002
> @@ -194,17 +194,33 @@ int do_syslog(int type, char * buf, int
> if (error)
> goto out;
> i = 0;
> +#ifdef CONFIG_ADEOS
> + ipipe_hw_spin_lock_disable(&logbuf_lock);
> +#else /* !CONFIG_ADEOS */
> spin_lock_irq(&logbuf_lock);
> +#endif /* CONFIG_ADEOS */
> while ((log_start != log_end) && i < len) {
> c = LOG_BUF(log_start);
> log_start++;
> +#ifdef CONFIG_ADEOS
> + ipipe_hw_spin_unlock_enable(&logbuf_lock);
> +#else /* !CONFIG_ADEOS */
> spin_unlock_irq(&logbuf_lock);
> +#endif /* CONFIG_ADEOS */
> __put_user(c,buf);
> buf++;
> i++;
> +#ifdef CONFIG_ADEOS
> + ipipe_hw_spin_lock_disable(&logbuf_lock);
> +#else /* !CONFIG_ADEOS */
> spin_lock_irq(&logbuf_lock);
> +#endif /* CONFIG_ADEOS */
> }
> +#ifdef CONFIG_ADEOS
> + ipipe_hw_spin_unlock_enable(&logbuf_lock);
> +#else /* !CONFIG_ADEOS */
> spin_unlock_irq(&logbuf_lock);
> +#endif /* CONFIG_ADEOS */
> error = i;
Why this ifdef hell and not something like:
lockbuf_lock();
bla
logbuf_unlock();
and have this defined in a header, say printk.h or whatever, with the
ifdefs?
- Arnaldo
Arnaldo Carvalho de Melo wrote:
> Why this ifdef hell and not something like:
>
> lockbuf_lock();
> bla
> logbuf_unlock();
>
> and have this defined in a header, say printk.h or whatever, with the
> ifdefs?
You're right, this is somewhat insane ;)
We'll fix it, thanks.
Karim
===================================================
Karim Yaghmour
[email protected]
Embedded and Real-Time Linux Expert
===================================================
Pavel Machek wrote:
> Are you actually able to use Adeos for something reasonable?
Sure, see below.
> You can't
> run two copies of linux, because they would fight over memory; right?
Currently we can't, you're right. But I've already detailed how to do
this in a paper I wrote last july on how to obtain Linux SMP clusters
with as few modifications to the kernel as possible. The paper is
available on the web:
http://opersys.com/ftp/pub/Adeos/practical-smp-clusters.ps
(If you stil can't access the web as said in the other email, I can
send you a copy off-list if you want.)
> Do you have something that can run alongside linux?
Certainly. According to some reports it's already used in some commercial
systems and, as today's RTAI announcement reads, it will be the basis
for the next release of RTAI.
What we need now is ports to other architectures than the i386. This
should be fairly simple for anyone familiar enough with the Linux
interrupt layer for any other arch.
Karim
===================================================
Karim Yaghmour
[email protected]
Embedded and Real-Time Linux Expert
===================================================
Hi!
> > > This is a patch for adding the Adeos nanokernel to the Linux kernel as
> > > described earlier:
> > > http://marc.theaimsgroup.com/?l=linux-kernel&m=102309348817485&w=2
> >
> > Maybe adding Docs/adeos.txt is good idea... (sorry can't access web
> > right now) --
>
> Right, we'll do that.
>
> > so this is aimed at being free rtlinux replacement?
>
> I'm not sure "replacement" is the appropriate description for this.
> The scheme used by rtlinux and rtai is a master-slave scheme where
> Linux is a slave to the rt executive. Adeos makes the entire scheme
> obsolete by making all the OSes running on the same hardware clients
> of the same nanokernel, regardless of whether the client OSes provide
> hard RT or not. None of these OSes need to have a "other OS" task,
> as rtlinux and rtai clearly do. Rather, when an OS is done using
> the machine, it tells Adeos that it's done and Adeos returns control
> to whichever other OS is next in the interrupt pipeline.
Are you actually able to use Adeos for something reasonable? You can't
run two copies of linux, because they would fight over memory; right?
Do you have something that can run alongside linux?
Pavel
--
Casualities in World Trade Center: ~3k dead inside the building,
cryptography in U.S.A. and free speech in Czech Republic.
On Tue, Sep 24, 2002 at 05:05:12PM -0400, Karim Yaghmour wrote:
>
> To be honest, nothing in Adeos is "new". Adeos is implemented on
> classic early '90s nanokernel research. I've listed a number of
> nanokernel papers in the paper I wrote on Adeos. A complete list
> of nanokernel papers would probably have hundreds of entries.
> Some of these nanokernels even had OS schedulers (exokernel for
> instance). All Adeos implements is a scheme for sharing the
> interrupts among the various OSes using an interrupt pipeline.
Hi,
are you planning to add spaces & portals, like in Space or Pebble?
best,
Jacob
Hello Pavel,
Pavel Machek wrote:
> > This is a patch for adding the Adeos nanokernel to the Linux kernel as
> > described earlier:
> > http://marc.theaimsgroup.com/?l=linux-kernel&m=102309348817485&w=2
>
> Maybe adding Docs/adeos.txt is good idea... (sorry can't access web
> right now) --
Right, we'll do that.
> so this is aimed at being free rtlinux replacement?
I'm not sure "replacement" is the appropriate description for this.
The scheme used by rtlinux and rtai is a master-slave scheme where
Linux is a slave to the rt executive. Adeos makes the entire scheme
obsolete by making all the OSes running on the same hardware clients
of the same nanokernel, regardless of whether the client OSes provide
hard RT or not. None of these OSes need to have a "other OS" task,
as rtlinux and rtai clearly do. Rather, when an OS is done using
the machine, it tells Adeos that it's done and Adeos returns control
to whichever other OS is next in the interrupt pipeline.
To be honest, nothing in Adeos is "new". Adeos is implemented on
classic early '90s nanokernel research. I've listed a number of
nanokernel papers in the paper I wrote on Adeos. A complete list
of nanokernel papers would probably have hundreds of entries.
Some of these nanokernels even had OS schedulers (exokernel for
instance). All Adeos implements is a scheme for sharing the
interrupts among the various OSes using an interrupt pipeline.
Karim
===================================================
Karim Yaghmour
[email protected]
Embedded and Real-Time Linux Expert
===================================================
Hi!
> This is a patch for adding the Adeos nanokernel to the Linux kernel as
> described earlier:
> http://marc.theaimsgroup.com/?l=linux-kernel&m=102309348817485&w=2
Maybe adding Docs/adeos.txt is good idea... (sorry can't access web
right now) -- so this is aimed at being free rtlinux replacement?
Pavel
--
Philips Velo 1: 1"x4"x8", 300gram, 60, 12MB, 40bogomips, linux, mutt,
details at http://atrey.karlin.mff.cuni.cz/~pavel/velo/index.html.
Hi!
> > You can't
> > run two copies of linux, because they would fight over memory; right?
>
> Currently we can't, you're right. But I've already detailed how to do
> this in a paper I wrote last july on how to obtain Linux SMP clusters
> with as few modifications to the kernel as possible. The paper is
> available on the web:
> http://opersys.com/ftp/pub/Adeos/practical-smp-clusters.ps
> (If you stil can't access the web as said in the other email, I can
> send you a copy off-list if you want.)
Its okay now, thanx.
> > Do you have something that can run alongside linux?
>
> Certainly. According to some reports it's already used in some commercial
> systems and, as today's RTAI announcement reads, it will be the basis
> for the next release of RTAI.
Ok. Good luck pushing it through linus ;-).
Pavel
--
Casualities in World Trade Center: ~3k dead inside the building,
cryptography in U.S.A. and free speech in Czech Republic.