Skip to contentSkip to conversation

Help with Ingo scheduler on IA64

Linux-ia64 Nick Pollitt 6 participants 34 messages Jan 12, 2002 – Jan 21, 2002

Subsystems (22)
lore
Share & tools
lore
#0 lore raw

I'm trying to get Ingo's scheduler working on IA64 but I've hit a dead-end with the head.S code. Ingo's patch removes init_tasks, so I've modified the assembly in head.S to point at runqueues(cpu)->idle, I think - it dies very early in the boot, and I'm not familiar with ia64 assembly.

Other issues, I had to build offsets.h by hand, and I moved some stuff from sched.c to sched.h. Other than that, it's H6 + ia64.

Anyone have any feedback on getting this booting?

Thanks
Nick

Quoted 6 lines · Ingo Molnar

the -H6 patch is available:

    http://redhat.com/~mingo/O(1)-scheduler/sched-O1-2.5.2-pre11-H6.patch
    http://redhat.com/~mingo/O(1)-scheduler/sched-O1-2.4.17-H6.patch
Signature · 3 lines
Nick Pollitt                                   phone: 650.933.7406
Scalable Linux Project                           fax: 650.932.0317
Silicon Graphics, Inc.                       [email protected]
arch/i386/kernel/apic.c +2 -4
diff -X dontdiff -Nur origlinux/arch/i386/kernel/apic.c mylinux/arch/i386/kernel/apic.c
@@ -785,8 +785,7 @@
 	 */
 
 	slice = clocks / (smp_num_cpus+1);
-	printk("cpu: %d, clocks: %d, slice: %d\n",
-		smp_processor_id(), clocks, slice);
+	printk("cpu: %d, clocks: %d, slice: %d\n", smp_processor_id(), clocks, slice);
 
 	/*
 	 * Wait for IRQ0's slice:
@@ -809,8 +808,7 @@
 
 	__setup_APIC_LVTT(clocks);
 
-	printk("CPU%d<T0:%d,T1:%d,D:%d,S:%d,C:%d>\n",
-			smp_processor_id(), t0, t1, delta, slice, clocks);
+	printk("CPU%d<T0:%d,T1:%d,D:%d,S:%d,C:%d>\n", smp_processor_id(), t0, t1, delta, slice, clocks);
 
 	__restore_flags(flags);
 }
arch/i386/kernel/nmi.c +1 -1
diff -X dontdiff -Nur origlinux/arch/i386/kernel/nmi.c mylinux/arch/i386/kernel/nmi.c
@@ -283,7 +283,7 @@
 			 * to get a message out.
 			 */
 			bust_spinlocks(1);
-			printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu);
+			printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip);
 			show_registers(regs);
 			printk("console shuts up ...\n");
 			console_silent();
arch/i386/kernel/process.c +1 -4
diff -X dontdiff -Nur origlinux/arch/i386/kernel/process.c mylinux/arch/i386/kernel/process.c
@@ -123,15 +123,12 @@
 void cpu_idle (void)
 {
 	/* endless idle loop with no priority at all */
-	init_idle();
-	current->nice = 20;
-	current->counter = -100;
 
 	while (1) {
 		void (*idle)(void) = pm_idle;
 		if (!idle)
 			idle = default_idle;
-		while (!current->need_resched)
+		if (!current->need_resched)
 			idle();
 		schedule();
 		check_pgt_cache();
arch/i386/kernel/smp.c +12 -2
diff -X dontdiff -Nur origlinux/arch/i386/kernel/smp.c mylinux/arch/i386/kernel/smp.c
@@ -105,7 +105,7 @@
 /* The 'big kernel lock' */
 spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
-struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
+struct tlb_state cpu_tlbstate[NR_CPUS] __cacheline_aligned = {[0 ... NR_CPUS-1] = { &init_mm, 0, }};
 
 /*
  * the following functions deal with sending IPIs between CPUs.
@@ -490,10 +490,20 @@
  * it goes straight through and wastes no time serializing
  * anything. Worst case is that we lose a reschedule ...
  */
-
 void smp_send_reschedule(int cpu)
 {
 	send_IPI_mask(1 << cpu, RESCHEDULE_VECTOR);
+}
+
+/*
+ * this function sends a reschedule IPI to all (other) CPUs.
+ * This should only be used if some 'global' task became runnable,
+ * such as a RT task, that must be handled now. The first CPU
+ * that manages to grab the task will run it.
+ */
+void smp_send_reschedule_all(void)
+{
+	send_IPI_allbutself(RESCHEDULE_VECTOR);
 }
 
 /*
arch/i386/kernel/smpboot.c +7 -9
diff -X dontdiff -Nur origlinux/arch/i386/kernel/smpboot.c mylinux/arch/i386/kernel/smpboot.c
@@ -308,14 +308,14 @@
 			if (tsc_values[i] < avg)
 				realdelta = -realdelta;
 
-			printk("BIOS BUG: CPU#%d improperly initialized, has %ld usecs TSC skew! FIXED.\n",
-				i, realdelta);
+			printk("BIOS BUG: CPU#%d improperly initialized, has %ld usecs TSC skew! FIXED.\n", i, realdelta);
 		}
 
 		sum += delta;
 	}
 	if (!buggy)
 		printk("passed.\n");
+		;
 }
 
 static void __init synchronize_tsc_ap (void)
@@ -365,7 +365,7 @@
 	 * (This works even if the APIC is not enabled.)
 	 */
 	phys_id = GET_APIC_ID(apic_read(APIC_ID));
-	cpuid = current->processor;
+	cpuid = cpu();
 	if (test_and_set_bit(cpuid, &cpu_online_map)) {
 		printk("huh, phys CPU#%d, CPU#%d already present??\n",
 					phys_id, cpuid);
@@ -471,6 +471,8 @@
 	 */
 	local_flush_tlb();
 
+	init_idle();
+	printk("cpu %d has done init idle, doing cpu_idle().\n", cpu());
 	return cpu_idle();
 }
 
@@ -803,16 +805,13 @@
 	if (!idle)
 		panic("No idle process for CPU %d", cpu);
 
-	idle->processor = cpu;
-	idle->cpus_runnable = 1 << cpu; /* we schedule the first task manually */
+	idle->cpu = cpu;
 
 	map_cpu_to_boot_apicid(cpu, apicid);
 
 	idle->thread.eip = (unsigned long) start_secondary;
 
-	del_from_runqueue(idle);
 	unhash_process(idle);
-	init_tasks[cpu] = idle;
 
 	/* start_eip had better be page-aligned! */
 	start_eip = setup_trampoline();
@@ -1020,8 +1019,7 @@
 	map_cpu_to_boot_apicid(0, boot_cpu_apicid);
 
 	global_irq_holder = 0;
-	current->processor = 0;
-	init_idle();
+	current->cpu = 0;
 	smp_tune_scheduling();
 
 	/*
arch/i386/mm/fault.c +2 -4
diff -X dontdiff -Nur origlinux/arch/i386/mm/fault.c mylinux/arch/i386/mm/fault.c
@@ -86,8 +86,7 @@
 
 out_of_memory:
 	if (current->pid == 1) {
-		current->policy |= SCHED_YIELD;
-		schedule();
+		yield();
 		goto survive;
 	}
 	goto bad_area;
@@ -342,8 +341,7 @@
 out_of_memory:
 	up_read(&mm->mmap_sem);
 	if (tsk->pid == 1) {
-		tsk->policy |= SCHED_YIELD;
-		schedule();
+		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
arch/ia64/kernel/head.S +8 -2
diff -X dontdiff -Nur origlinux/arch/ia64/kernel/head.S mylinux/arch/ia64/kernel/head.S
@@ -124,6 +124,7 @@
 #define isAP	p2	// are we an Application Processor?
 #define isBP	p3	// are we the Bootstrap Processor?
 
+
 #ifdef CONFIG_SMP
 	/*
 	 * Find the init_task for the currently booting CPU.  At poweron, and in
@@ -132,9 +133,14 @@
 	movl r3=cpucount
  	;;
 	ld4 r3=[r3]		// r3 <- smp_processor_id()
-	movl r2=init_tasks
+	movl r2=runqueues
+	movl r4=IA64_RUNQUEUE_SIZE
 	;;
-	shladd r2=r3,3,r2
+1:      add r2=r2,r4
+        ;;
+        br.cloop.sptk.many 1b
+        ;;
+        addl r2=IA64_RUNQUEUE_IDLE_OFFSET,r2
 	;;
 	ld8 r2=[r2]
 #else
arch/ia64/kernel/process.c +1 -4
diff -X dontdiff -Nur origlinux/arch/ia64/kernel/process.c mylinux/arch/ia64/kernel/process.c
@@ -125,9 +125,6 @@
 cpu_idle (void *unused)
 {
 	/* endless idle loop with no priority at all */
-	init_idle();
-	current->nice = 20;
-	current->counter = -100;
 
 
 	while (1) {
@@ -136,7 +133,7 @@
 			min_xtp();
 #endif
 
-		while (!current->need_resched) {
+		if (!current->need_resched) {
 #ifdef CONFIG_IA64_SGI_SN
 			snidle();
 #endif
arch/ia64/kernel/setup.c +3 -3
diff -X dontdiff -Nur origlinux/arch/ia64/kernel/setup.c mylinux/arch/ia64/kernel/setup.c
@@ -375,10 +375,10 @@
 {
 #ifdef CONFIG_SMP
 #	define lpj	c->loops_per_jiffy
-#	define cpu	c->processor
+#	define cpum	c->processor
 #else
 #	define lpj	loops_per_jiffy
-#	define cpu	0
+#	define cpum	0
 #endif
 	char family[32], features[128], *cp;
 	struct cpuinfo_ia64 *c = v;
@@ -417,7 +417,7 @@
 		   "cpu MHz    : %lu.%06lu\n"
 		   "itc MHz    : %lu.%06lu\n"
 		   "BogoMIPS   : %lu.%02lu\n\n",
-		   cpu, c->vendor, family, c->model, c->revision, c->archrev,
+		   cpum, c->vendor, family, c->model, c->revision, c->archrev,
 		   features, c->ppn, c->number,
 		   c->proc_freq / 1000000, c->proc_freq % 1000000,
 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
arch/ia64/kernel/smp.c +6 -0
diff -X dontdiff -Nur origlinux/arch/ia64/kernel/smp.c mylinux/arch/ia64/kernel/smp.c
@@ -186,6 +186,12 @@
 }
 
 void
+smp_send_reschedule_all(void)
+{
+	send_IPI_all(IA64_IPI_RESCHEDULE);
+}
+
+void
 smp_flush_tlb_all (void)
 {
 	smp_call_function ((void (*)(void *))__flush_tlb_all,0,1,1);
arch/ia64/kernel/smpboot.c +4 -5
diff -X dontdiff -Nur origlinux/arch/ia64/kernel/smpboot.c mylinux/arch/ia64/kernel/smpboot.c
@@ -23,6 +23,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
+#include <linux/sched.h>
 
 #include <asm/atomic.h>
 #include <asm/bitops.h>
@@ -323,7 +324,7 @@
 	extern void perfmon_init_percpu(void);
 #endif
 
-	cpuid = smp_processor_id();
+	cpuid = cpu();
 	phys_id = hard_smp_processor_id();
 
 	if (test_and_set_bit(cpuid, &cpu_online_map)) {
@@ -416,13 +417,11 @@
 	if (!idle)
 		panic("No idle process for CPU %d", cpu);
 
-	task_set_cpu(idle, cpu);	/* we schedule the first task manually */
+	idle->cpu = cpu();
 
 	ia64_cpu_to_sapicid[cpu] = sapicid;
 
-	del_from_runqueue(idle);
 	unhash_process(idle);
-	init_tasks[cpu] = idle;
 
 	Dprintk("Sending wakeup vector %u to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
 
@@ -481,7 +480,7 @@
 	printk("Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
 
 	global_irq_holder = 0;
-	current->processor = 0;
+	current->cpu = 0;
 	init_idle();
 
 	/*
arch/ia64/mm/fault.c +0 -2
diff -X dontdiff -Nur origlinux/arch/ia64/mm/fault.c mylinux/arch/ia64/mm/fault.c
@@ -194,8 +194,6 @@
   out_of_memory:
 	up_read(&mm->mmap_sem);
 	if (current->pid == 1) {
-		current->policy |= SCHED_YIELD;
-		schedule();
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
arch/ia64/tools/print_offsets.c +3 -1
diff -X dontdiff -Nur origlinux/arch/ia64/tools/print_offsets.c mylinux/arch/ia64/tools/print_offsets.c
@@ -50,11 +50,12 @@
     { "IA64_CPU_SIZE",			sizeof (struct cpuinfo_ia64) },
     { "SIGFRAME_SIZE",			sizeof (struct sigframe) },
     { "UNW_FRAME_INFO_SIZE",		sizeof (struct unw_frame_info) },
+    { "IA64_RUNQUEUE_SIZE",		sizeof (struct runqueue) },
     { "", 0 },			/* spacer */
     { "IA64_TASK_PTRACE_OFFSET",	offsetof (struct task_struct, ptrace) },
     { "IA64_TASK_SIGPENDING_OFFSET",	offsetof (struct task_struct, sigpending) },
     { "IA64_TASK_NEED_RESCHED_OFFSET",	offsetof (struct task_struct, need_resched) },
-    { "IA64_TASK_PROCESSOR_OFFSET",	offsetof (struct task_struct, processor) },
+    { "IA64_TASK_PROCESSOR_OFFSET",	offsetof (struct task_struct, cpu) },
     { "IA64_TASK_THREAD_OFFSET",	offsetof (struct task_struct, thread) },
     { "IA64_TASK_THREAD_KSP_OFFSET",	offsetof (struct task_struct, thread.ksp) },
 #ifdef CONFIG_PERFMON
@@ -62,6 +63,7 @@
 #endif
     { "IA64_TASK_PID_OFFSET",		offsetof (struct task_struct, pid) },
     { "IA64_TASK_MM_OFFSET",		offsetof (struct task_struct, mm) },
+    { "IA64_RUNQUEUE_IDLE_OFFSET",	offsetof (struct runqueue, idle) },
     { "IA64_PT_REGS_CR_IPSR_OFFSET",	offsetof (struct pt_regs, cr_ipsr) },
     { "IA64_PT_REGS_CR_IIP_OFFSET",	offsetof (struct pt_regs, cr_iip) },
     { "IA64_PT_REGS_CR_IFS_OFFSET",	offsetof (struct pt_regs, cr_ifs) },
drivers/block/loop.c +0 -3
diff -X dontdiff -Nur origlinux/drivers/block/loop.c mylinux/drivers/block/loop.c
@@ -570,9 +570,6 @@
 	flush_signals(current);
 	spin_unlock_irq(&current->sigmask_lock);
 
-	current->policy = SCHED_OTHER;
-	current->nice = -20;
-
 	spin_lock_irq(&lo->lo_lock);
 	lo->lo_state = Lo_bound;
 	atomic_inc(&lo->lo_pending);
drivers/ide/ataraid.c +4 -10
diff -X dontdiff -Nur origlinux/drivers/ide/ataraid.c mylinux/drivers/ide/ataraid.c
@@ -121,11 +121,8 @@
 	void *ptr = NULL;
 	while (!ptr) {
 		ptr=kmalloc(sizeof(struct buffer_head),GFP_NOIO);
-		if (!ptr) {
-			__set_current_state(TASK_RUNNING);
-	                current->policy |= SCHED_YIELD;
-	                schedule();             
-		}
+		if (!ptr)
+			yield();
 	}
 	return ptr;
 }
@@ -137,11 +134,8 @@
 	void *ptr = NULL;
 	while (!ptr) {
 		ptr=kmalloc(sizeof(struct ataraid_bh_private),GFP_NOIO);
-		if (!ptr) {
-			__set_current_state(TASK_RUNNING);
-	                current->policy |= SCHED_YIELD;
-	                schedule();             
-		}
+		if (!ptr)
+			yield();
 	}
 	return ptr;
 }
drivers/md/md.c +1 -11
diff -X dontdiff -Nur origlinux/drivers/md/md.c mylinux/drivers/md/md.c
@@ -2930,8 +2930,6 @@
 	 * bdflush, otherwise bdflush will deadlock if there are too
 	 * many dirty RAID5 blocks.
 	 */
-	current->policy = SCHED_OTHER;
-	current->nice = -20;
 	md_unlock_kernel();
 
 	complete(thread->event);
@@ -3381,11 +3379,6 @@
 	       "(but not more than %d KB/sec) for reconstruction.\n",
 	       sysctl_speed_limit_max);
 
-	/*
-	 * Resync has low priority.
-	 */
-	current->nice = 19;
-
 	is_mddev_idle(mddev); /* this also initializes IO event counters */
 	for (m = 0; m < SYNC_MARKS; m++) {
 		mark[m] = jiffies;
@@ -3463,16 +3456,13 @@
 		currspeed = (j-mddev->resync_mark_cnt)/2/((jiffies-mddev->resync_mark)/HZ +1) +1;
 
 		if (currspeed > sysctl_speed_limit_min) {
-			current->nice = 19;
-
 			if ((currspeed > sysctl_speed_limit_max) ||
 					!is_mddev_idle(mddev)) {
 				current->state = TASK_INTERRUPTIBLE;
 				md_schedule_timeout(HZ/4);
 				goto repeat;
 			}
-		} else
-			current->nice = -20;
+		}
 	}
 	printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev));
 	err = 0;
drivers/net/slip.c +2 -4
diff -X dontdiff -Nur origlinux/drivers/net/slip.c mylinux/drivers/net/slip.c
@@ -1393,10 +1393,8 @@
 		/* First of all: check for active disciplines and hangup them.
 		 */
 		do {
-			if (busy) {
-				current->counter = 0;
-				schedule();
-			}
+			if (busy)
+				sys_sched_yield();
 
 			busy = 0;
 			local_bh_disable();
fs/binfmt_elf.c +1 -1
diff -X dontdiff -Nur origlinux/fs/binfmt_elf.c mylinux/fs/binfmt_elf.c
@@ -1143,7 +1143,7 @@
 	psinfo.pr_state = i;
 	psinfo.pr_sname = (i < 0 || i > 5) ? '.' : "RSDZTD"[i];
 	psinfo.pr_zomb = psinfo.pr_sname == 'Z';
-	psinfo.pr_nice = current->nice;
+	psinfo.pr_nice = current->__nice;
 	psinfo.pr_flag = current->flags;
 	psinfo.pr_uid = NEW_TO_OLD_UID(current->uid);
 	psinfo.pr_gid = NEW_TO_OLD_GID(current->gid);
fs/buffer.c +1 -3
diff -X dontdiff -Nur origlinux/fs/buffer.c mylinux/fs/buffer.c
@@ -725,9 +725,7 @@
 	wakeup_bdflush();
 	try_to_free_pages(zone, GFP_NOFS, 0);
 	run_task_queue(&tq_disk);
-	current->policy |= SCHED_YIELD;
-	__set_current_state(TASK_RUNNING);
-	schedule();
+	sys_sched_yield();
 }
 
 void init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private)
fs/jbd/journal.c +3 -6
diff -X dontdiff -Nur origlinux/fs/jbd/journal.c mylinux/fs/jbd/journal.c
@@ -460,8 +460,7 @@
 			printk (KERN_NOTICE __FUNCTION__
 				": ENOMEM at get_unused_buffer_head, "
 				"trying again.\n");
-			current->policy |= SCHED_YIELD;
-			schedule();
+			yield();
 		}
 	} while (!new_bh);
 	/* keep subsequent assertions sane */
@@ -1539,8 +1538,7 @@
 			last_warning = jiffies;
 		}
 		
-		current->policy |= SCHED_YIELD;
-		schedule();
+		yield();
 	}
 }
 
@@ -1598,8 +1596,7 @@
 			last_warning = jiffies;
 		}
 		while (ret == 0) {
-			current->policy |= SCHED_YIELD;
-			schedule();
+			yield();
 			ret = kmem_cache_alloc(journal_head_cache, GFP_NOFS);
 		}
 	}
fs/jbd/revoke.c +1 -2
diff -X dontdiff -Nur origlinux/fs/jbd/revoke.c mylinux/fs/jbd/revoke.c
@@ -137,8 +137,7 @@
 	if (!journal_oom_retry)
 		return -ENOMEM;
 	jbd_debug(1, "ENOMEM in " __FUNCTION__ ", retrying.\n");
-	current->policy |= SCHED_YIELD;
-	schedule();
+	yield();
 	goto repeat;
 }
 
fs/jbd/transaction.c +1 -2
diff -X dontdiff -Nur origlinux/fs/jbd/transaction.c mylinux/fs/jbd/transaction.c
@@ -1377,8 +1377,7 @@
 		do {
 			old_handle_count = transaction->t_handle_count;
 			set_current_state(TASK_RUNNING);
-			current->policy |= SCHED_YIELD;
-			schedule();
+			yield();
 		} while (old_handle_count != transaction->t_handle_count);
 	}
 
fs/jffs2/background.c +0 -3
diff -X dontdiff -Nur origlinux/fs/jffs2/background.c mylinux/fs/jffs2/background.c
@@ -106,9 +106,6 @@
 
         sprintf(current->comm, "jffs2_gcd_mtd%d", c->mtd->index);
 
-	/* FIXME in the 2.2 backport */
-	current->nice = 10;
-
 	for (;;) {
 		spin_lock_irq(&current->sigmask_lock);
 		siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
fs/locks.c +1 -2
diff -X dontdiff -Nur origlinux/fs/locks.c mylinux/fs/locks.c
@@ -445,8 +445,7 @@
 			/* Let the blocked process remove waiter from the
 			 * block list when it gets scheduled.
 			 */
-			current->policy |= SCHED_YIELD;
-			schedule();
+			yield();
 		} else {
 			/* Remove waiter from the block list, because by the
 			 * time it wakes up blocker won't exist any more.
fs/nfs/pagelist.c +1 -2
diff -X dontdiff -Nur origlinux/fs/nfs/pagelist.c mylinux/fs/nfs/pagelist.c
@@ -96,8 +96,7 @@
 			continue;
 		if (signalled() && (server->flags & NFS_MOUNT_INTR))
 			return ERR_PTR(-ERESTARTSYS);
-		current->policy = SCHED_YIELD;
-		schedule();
+		yield();
 	}
 
 	/* Initialize the request struct. Initially, we assume a
fs/proc/array.c +7 -4
diff -X dontdiff -Nur origlinux/fs/proc/array.c mylinux/fs/proc/array.c
@@ -335,9 +335,12 @@
 
 	/* scale priority and nice values from timeslices to -20..20 */
 	/* to make it look like a "normal" Unix priority/nice value  */
-	priority = task->counter;
-	priority = 20 - (priority * 10 + DEF_COUNTER / 2) / DEF_COUNTER;
-	nice = task->nice;
+	priority = task->prio;
+	if (priority >= MAX_RT_PRIO)
+		priority -= MAX_RT_PRIO;
+	else
+		priority = priority-100;
+	nice = task->__nice;
 
 	read_lock(&tasklist_lock);
 	ppid = task->pid ? task->p_opptr->pid : 0;
@@ -387,7 +390,7 @@
 		task->nswap,
 		task->cnswap,
 		task->exit_signal,
-		task->processor);
+		task->cpu);
 	if(mm)
 		mmput(mm);
 	return res;
fs/proc/proc_misc.c +5 -5
diff -X dontdiff -Nur origlinux/fs/proc/proc_misc.c mylinux/fs/proc/proc_misc.c
@@ -85,11 +85,11 @@
 	a = avenrun[0] + (FIXED_1/200);
 	b = avenrun[1] + (FIXED_1/200);
 	c = avenrun[2] + (FIXED_1/200);
-	len = sprintf(page,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
+	len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
 		LOAD_INT(a), LOAD_FRAC(a),
 		LOAD_INT(b), LOAD_FRAC(b),
 		LOAD_INT(c), LOAD_FRAC(c),
-		nr_running, nr_threads, last_pid);
+		nr_running(), nr_threads, last_pid);
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
@@ -101,7 +101,7 @@
 	int len;
 
 	uptime = jiffies;
-	idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime;
+	idle = init_task.times.tms_utime + init_task.times.tms_stime;
 
 	/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
 	   that would overflow about every five days at HZ == 100.
@@ -303,10 +303,10 @@
 	}
 
 	len += sprintf(page + len,
-		"\nctxt %u\n"
+		"\nctxt %lu\n"
 		"btime %lu\n"
 		"processes %lu\n",
-		kstat.context_swtch,
+		nr_context_switches(),
 		xtime.tv_sec - jif / HZ,
 		total_forks);
 
fs/reiserfs/buffer2.c +3 -4
diff -X dontdiff -Nur origlinux/fs/reiserfs/buffer2.c mylinux/fs/reiserfs/buffer2.c
@@ -33,8 +33,7 @@
 			buffer_journal_dirty(bh) ? ' ' : '!');
     }
     run_task_queue(&tq_disk);
-    current->policy |= SCHED_YIELD;
-    schedule();
+    yield();
   }
   if (repeat_counter > 30000000) {
     reiserfs_warning("vs-3051: done waiting, ignore vs-3050 messages for (%b)\n", bh) ;
@@ -52,11 +51,11 @@
 struct buffer_head  * reiserfs_bread (struct super_block *super, int n_block, int n_size) 
 {
     struct buffer_head  *result;
-    PROC_EXP( unsigned int ctx_switches = kstat.context_swtch );
+    PROC_EXP( unsigned int ctx_switches = nr_context_switches(); );
 
     result = bread (super -> s_dev, n_block, n_size);
     PROC_INFO_INC( super, breads );
-    PROC_EXP( if( kstat.context_swtch != ctx_switches ) 
+    PROC_EXP( if( nr_context_switches() != ctx_switches ) 
 	      PROC_INFO_INC( super, bread_miss ) );
     return result;
 }
fs/reiserfs/journal.c +1 -2
diff -X dontdiff -Nur origlinux/fs/reiserfs/journal.c mylinux/fs/reiserfs/journal.c
@@ -149,8 +149,7 @@
   }
   bn = allocate_bitmap_node(p_s_sb) ;
   if (!bn) {
-    current->policy |= SCHED_YIELD ;
-    schedule() ;
+    yield();
     goto repeat ;
   }
   return bn ;
fs/ufs/truncate.c +1 -4
diff -X dontdiff -Nur origlinux/fs/ufs/truncate.c mylinux/fs/ufs/truncate.c
@@ -448,10 +448,7 @@
 		if (IS_SYNC(inode) && (inode->i_state & I_DIRTY))
 			ufs_sync_inode (inode);
 		run_task_queue(&tq_disk);
-		current->policy |= SCHED_YIELD;
-		schedule ();
-
-
+		yield();
 	}
 	offset = inode->i_size & uspi->s_fshift;
 	if (offset) {
include/asm-i386/bitops.h +8 -0
diff -X dontdiff -Nur origlinux/include/asm-i386/bitops.h mylinux/include/asm-i386/bitops.h
@@ -75,6 +75,14 @@
 		:"=m" (ADDR)
 		:"Ir" (nr));
 }
+
+static __inline__ void __clear_bit(int nr, volatile void * addr)
+{
+	__asm__ __volatile__(
+		"btrl %1,%0"
+		:"=m" (ADDR)
+		:"Ir" (nr));
+}
 #define smp_mb__before_clear_bit()	barrier()
 #define smp_mb__after_clear_bit()	barrier()
 
include/asm-i386/mmu_context.h +22 -0
diff -X dontdiff -Nur origlinux/include/asm-i386/mmu_context.h mylinux/include/asm-i386/mmu_context.h
@@ -7,6 +7,28 @@
 #include <asm/pgalloc.h>
 
 /*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 168-bit bitmap where the first 128 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 168
+ * bits is cleared.
+ */
+#if MAX_RT_PRIO != 128 || MAX_PRIO != 168
+# error update this function.
+#endif
+
+static inline int sched_find_first_zero_bit(unsigned long *b)
+{
+	unsigned int rt;
+
+	rt = b[0] & b[1] & b[2] & b[3];
+	if (unlikely(rt != 0xffffffff))
+		return find_first_zero_bit(b, MAX_RT_PRIO);
+
+	if (b[4] != ~0)
+		return ffz(b[4]) + MAX_RT_PRIO;
+	return ffz(b[5]) + 32 + MAX_RT_PRIO;
+}
+/*
  * possibly do the LDT unload here?
  */
 #define destroy_context(mm)		do { } while(0)
include/asm-i386/pgalloc.h +1 -0
diff -X dontdiff -Nur origlinux/include/asm-i386/pgalloc.h mylinux/include/asm-i386/pgalloc.h
@@ -224,6 +224,7 @@
 {
 	struct mm_struct *active_mm;
 	int state;
+	char __cacheline_padding[24];
 };
 extern struct tlb_state cpu_tlbstate[NR_CPUS];
 
include/asm-i386/smp.h +2 -13
diff -X dontdiff -Nur origlinux/include/asm-i386/smp.h mylinux/include/asm-i386/smp.h
@@ -63,6 +63,7 @@
 extern void smp_flush_tlb(void);
 extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
 extern void smp_send_reschedule(int cpu);
+extern void smp_send_reschedule_all(void);
 extern void smp_invalidate_rcv(void);		/* Process an NMI */
 extern void (*mtrr_hook) (void);
 extern void zap_low_mappings (void);
@@ -104,7 +105,7 @@
  * so this is correct in the x86 case.
  */
 
-#define smp_processor_id() (current->processor)
+#define smp_processor_id() (current->cpu)
 
 static __inline int hard_smp_processor_id(void)
 {
@@ -121,18 +122,6 @@
 #endif /* !__ASSEMBLY__ */
 
 #define NO_PROC_ID		0xFF		/* No processor magic marker */
-
-/*
- *	This magic constant controls our willingness to transfer
- *	a process across CPUs. Such a transfer incurs misses on the L1
- *	cache, and on a P6 or P5 with multiple L2 caches L2 hits. My
- *	gut feeling is this will vary by board in value. For a board
- *	with separate L2 cache it probably depends also on the RSS, and
- *	for a board with shared L2 cache it ought to decay fast as other
- *	processes are run.
- */
- 
-#define PROC_CHANGE_PENALTY	15		/* Schedule penalty */
 
 #endif
 #endif
include/asm-ia64/bitops.h +1 -0
diff -X dontdiff -Nur origlinux/include/asm-ia64/bitops.h mylinux/include/asm-ia64/bitops.h
@@ -368,6 +368,7 @@
 
 #ifdef __KERNEL__
 
+#define __clear_bit(nr, addr)		clear_bit(nr, addr)
 #define ext2_set_bit                 test_and_set_bit
 #define ext2_clear_bit               test_and_clear_bit
 #define ext2_test_bit                test_bit
include/asm-ia64/mmu_context.h +1 -0
diff -X dontdiff -Nur origlinux/include/asm-ia64/mmu_context.h mylinux/include/asm-ia64/mmu_context.h
@@ -118,6 +118,7 @@
 	reload_context(next);
 }
 
+#define sched_find_first_zero_bit(bitmap)	ffz(bitmap)
 #define switch_mm(prev_mm,next_mm,next_task,cpu)	activate_mm(prev_mm, next_mm)
 
 # endif /* ! __ASSEMBLY__ */
include/asm-ia64/smp.h +1 -7
diff -X dontdiff -Nur origlinux/include/asm-ia64/smp.h mylinux/include/asm-ia64/smp.h
@@ -27,7 +27,7 @@
 #define SMP_IRQ_REDIRECTION	(1 << 0)
 #define SMP_IPI_REDIRECTION	(1 << 1)
 
-#define smp_processor_id()	(current->processor)
+#define smp_processor_id()	(current->cpu)
 
 extern struct smp_boot_data {
 	int cpu_count;
@@ -109,12 +109,6 @@
 }
 
 #define NO_PROC_ID		0xffffffff	/* no processor magic marker */
-
-/*
- * Extra overhead to move a task from one cpu to another (due to TLB and cache misses).
- * Expressed in "negative nice value" units (larger number means higher priority/penalty).
- */
-#define PROC_CHANGE_PENALTY	20
 
 extern void __init init_smp_config (void);
 extern void smp_do_timer (struct pt_regs *regs);
include/linux/kernel_stat.h +2 -1
diff -X dontdiff -Nur origlinux/include/linux/kernel_stat.h mylinux/include/linux/kernel_stat.h
@@ -32,10 +32,11 @@
 	unsigned int ipackets, opackets;
 	unsigned int ierrors, oerrors;
 	unsigned int collisions;
-	unsigned int context_swtch;
 };
 
 extern struct kernel_stat kstat;
+
+extern unsigned long nr_context_switches(void);
 
 #if !defined(CONFIG_ARCH_S390)
 /*
include/linux/list.h +2 -0
diff -X dontdiff -Nur origlinux/include/linux/list.h mylinux/include/linux/list.h
@@ -19,6 +19,8 @@
 	struct list_head *next, *prev;
 };
 
+typedef struct list_head list_t;
+
 #define LIST_HEAD_INIT(name) { &(name), &(name) }
 
 #define LIST_HEAD(name) \
include/linux/sched.h +143 -64

306 lines not on this page · raw message

include/linux/smp.h +8 -0
diff -X dontdiff -Nur origlinux/include/linux/smp.h mylinux/include/linux/smp.h
@@ -77,6 +77,14 @@
 #define cpu_number_map(cpu)			0
 #define smp_call_function(func,info,retry,wait)	({ 0; })
 #define cpu_online_map				1
+static inline void smp_send_reschedule(int cpu) { }
+static inline void smp_send_reschedule_all(void) { }
 
 #endif
+
+/*
+ * Common definitions:
+ */
+#define cpu()					smp_processor_id()
+
 #endif
init/main.c +20 -23

73 lines not on this page · raw message

kernel/capability.c +2 -0
diff -X dontdiff -Nur origlinux/kernel/capability.c mylinux/kernel/capability.c
@@ -8,6 +8,8 @@
 #include <linux/mm.h>
 #include <asm/uaccess.h>
 
+unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
+
 kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
 
 /* Note: never hold tasklist_lock while spinning for this one */
kernel/exit.c +104 -41

159 lines not on this page · raw message

kernel/fork.c +42 -13

108 lines not on this page · raw message

kernel/ksyms.c +4 -0
diff -X dontdiff -Nur origlinux/kernel/ksyms.c mylinux/kernel/ksyms.c
@@ -437,6 +437,9 @@
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 EXPORT_SYMBOL(schedule);
 EXPORT_SYMBOL(schedule_timeout);
+EXPORT_SYMBOL(sys_sched_yield);
+EXPORT_SYMBOL(set_user_nice);
+EXPORT_SYMBOL(set_cpus_allowed);
 EXPORT_SYMBOL(jiffies);
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
@@ -448,6 +451,7 @@
 
 EXPORT_SYMBOL(kstat);
 EXPORT_SYMBOL(nr_running);
+EXPORT_SYMBOL(nr_context_switches);
 
 /* misc */
 EXPORT_SYMBOL(panic);
kernel/printk.c +1 -0
diff -X dontdiff -Nur origlinux/kernel/printk.c mylinux/kernel/printk.c
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>			/* For in_interrupt() */
+#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 
kernel/ptrace.c +1 -14
diff -X dontdiff -Nur origlinux/kernel/ptrace.c mylinux/kernel/ptrace.c
@@ -31,20 +31,7 @@
 		if (child->state != TASK_STOPPED)
 			return -ESRCH;
 #ifdef CONFIG_SMP
-		/* Make sure the child gets off its CPU.. */
-		for (;;) {
-			task_lock(child);
-			if (!task_has_cpu(child))
-				break;
-			task_unlock(child);
-			do {
-				if (child->state != TASK_STOPPED)
-					return -ESRCH;
-				barrier();
-				cpu_relax();
-			} while (task_has_cpu(child));
-		}
-		task_unlock(child);
+		wait_task_inactive(child);
 #endif		
 	}
 
kernel/sched.c +850 -719

1,597 lines not on this page · raw message

kernel/signal.c +3 -6
diff -X dontdiff -Nur origlinux/kernel/signal.c mylinux/kernel/signal.c

Lines of this file are not shown. View the raw message.

kernel/softirq.c +9 -12
diff -X dontdiff -Nur origlinux/kernel/softirq.c mylinux/kernel/softirq.c

Lines of this file are not shown. View the raw message.

kernel/sys.c +3 -3
diff -X dontdiff -Nur origlinux/kernel/sys.c mylinux/kernel/sys.c

Lines of this file are not shown. View the raw message.

kernel/timer.c +91 -7

98 lines not on this page · raw message

mm/highmem.c +2 -6
diff -X dontdiff -Nur origlinux/mm/highmem.c mylinux/mm/highmem.c

Lines of this file are not shown. View the raw message.

mm/oom_kill.c +3 -4
diff -X dontdiff -Nur origlinux/mm/oom_kill.c mylinux/mm/oom_kill.c

Lines of this file are not shown. View the raw message.

mm/page_alloc.c +1 -3
diff -X dontdiff -Nur origlinux/mm/page_alloc.c mylinux/mm/page_alloc.c

Lines of this file are not shown. View the raw message.

net/ipv4/tcp_output.c +1 -2
diff -X dontdiff -Nur origlinux/net/ipv4/tcp_output.c mylinux/net/ipv4/tcp_output.c

Lines of this file are not shown. View the raw message.

net/sched/sch_generic.c +2 -4
diff -X dontdiff -Nur origlinux/net/sched/sch_generic.c mylinux/net/sched/sch_generic.c

Lines of this file are not shown. View the raw message.

net/socket.c +1 -2
diff -X dontdiff -Nur origlinux/net/socket.c mylinux/net/socket.c

Lines of this file are not shown. View the raw message.

net/sunrpc/sched.c +3 -6
diff -X dontdiff -Nur origlinux/net/sunrpc/sched.c mylinux/net/sunrpc/sched.c

Lines of this file are not shown. View the raw message.

net/unix/af_unix.c +2 -4
diff -X dontdiff -Nur origlinux/net/unix/af_unix.c mylinux/net/unix/af_unix.c

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Part of the diff is not shown here. View the raw message.

#1 lore raw

Nick> I'm trying to get Ingo's scheduler working on IA64 but I've hit a Nick> dead-end with the head.S code. Ingo's patch removes init_tasks, Nick> so I've modified the assembly in head.S to point at Nick> runqueues(cpu)->idle, I think - it dies very early in the boot, Nick> and I'm not familiar with ia64 assembly.

Nick> Other issues, I had to build offsets.h by hand, and I moved some Nick> stuff from sched.c to sched.h. Other than that, it's H6 + ia64.

Nick> Anyone have any feedback on getting this booting?

This may not help you but just fyi: I'm planning to sync up with 2.5 next week (2.5.2 by then, hopefully). Of course, if someone else has a working patch by then, I'll take it. ;-)

	--david
#2 lore raw
In reply to Nick Pollitt

Hi,

I don't think that runqueues(cpu)->idle is set when you try to access it from head.S. It is much easier to reintroduce init_tasks and leave head.S as it is. Then no changes are needed in Ingo's patch for sched.h and sched.c. Ingo, could you please comment?

Please find attached an ia64 patch which should be applied over 2.4.17 + ia64 + sched-O1-2.4.17-H7.patch

It doesn't boot yet, the system (2CPU BigSur) crashes in
schedule() <- cpu_idle() <- rest_init() <- start_kernel()
Maybe somebody has an idea?

Thanks,

Erich

---
Erich Focht <[email protected]>
NEC European Supercomputer Systems, European HPC Technology Center

Quoted 15 lines · Nick Pollitt

I'm trying to get Ingo's scheduler working on IA64 but I've hit a dead-end with the head.S code. Ingo's patch removes init_tasks, so I've modified the assembly in head.S to point at runqueues(cpu)->idle, I think - it dies very early in the boot, and I'm not familiar with ia64 assembly.

Other issues, I had to build offsets.h by hand, and I moved some stuff from sched.c to sched.h. Other than that, it's H6 + ia64.

Anyone have any feedback on getting this booting?

Thanks
Nick

Quoted 13 lines
Quoted 6 lines · Ingo Molnar

the -H6 patch is available:

    http://redhat.com/~mingo/O(1)-scheduler/sched-O1-2.5.2-pre11-H6.patch
    http://redhat.com/~mingo/O(1)-scheduler/sched-O1-2.4.17-H6.patch
Signature · 3 lines
Nick Pollitt                                   phone: 650.933.7406
Scalable Linux Project                           fax: 650.932.0317
Silicon Graphics, Inc.                       [email protected]
arch/ia64/kernel/process.c +1 -5
diff -urN 2.4.17-O1/arch/ia64/kernel/process.c 2.4.17-O1-H7/arch/ia64/kernel/process.c
@@ -125,9 +125,6 @@
 cpu_idle (void *unused)
 {
 	/* endless idle loop with no priority at all */
-	init_idle();
-	current->nice = 20;
-	current->counter = -100;
 
 
 	while (1) {
@@ -136,11 +133,10 @@
 			min_xtp();
 #endif
 
-		while (!current->need_resched) {
+		if (!current->need_resched) {
 #ifdef CONFIG_IA64_SGI_SN
 			snidle();
 #endif
-			continue;
 		}
 
 #ifdef CONFIG_IA64_SGI_SN
arch/ia64/kernel/setup.c +3 -3
diff -urN 2.4.17-O1/arch/ia64/kernel/setup.c 2.4.17-O1-H7/arch/ia64/kernel/setup.c
@@ -375,10 +375,10 @@
 {
 #ifdef CONFIG_SMP
 #	define lpj	c->loops_per_jiffy
-#	define cpu	c->processor
+#	define cpum	c->processor
 #else
 #	define lpj	loops_per_jiffy
-#	define cpu	0
+#	define cpum	0
 #endif
 	char family[32], features[128], *cp;
 	struct cpuinfo_ia64 *c = v;
@@ -417,7 +417,7 @@
 		   "cpu MHz    : %lu.%06lu\n"
 		   "itc MHz    : %lu.%06lu\n"
 		   "BogoMIPS   : %lu.%02lu\n\n",
-		   cpu, c->vendor, family, c->model, c->revision, c->archrev,
+		   cpum, c->vendor, family, c->model, c->revision, c->archrev,
 		   features, c->ppn, c->number,
 		   c->proc_freq / 1000000, c->proc_freq % 1000000,
 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
arch/ia64/kernel/smp.c +6 -0
diff -urN 2.4.17-O1/arch/ia64/kernel/smp.c 2.4.17-O1-H7/arch/ia64/kernel/smp.c
@@ -186,6 +186,12 @@
 }
 
 void
+smp_send_reschedule_all(void)
+{
+	send_IPI_all(IA64_IPI_RESCHEDULE);
+}
+
+void
 smp_flush_tlb_all (void)
 {
 	smp_call_function ((void (*)(void *))__flush_tlb_all,0,1,1);
arch/ia64/kernel/smpboot.c +5 -5
diff -urN 2.4.17-O1/arch/ia64/kernel/smpboot.c 2.4.17-O1-H7/arch/ia64/kernel/smpboot.c
@@ -23,6 +23,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
+#include <linux/sched.h>
 
 #include <asm/atomic.h>
 #include <asm/bitops.h>
@@ -323,7 +324,7 @@
 	extern void perfmon_init_percpu(void);
 #endif
 
-	cpuid = smp_processor_id();
+	cpuid = cpu();
 	phys_id = hard_smp_processor_id();
 
 	if (test_and_set_bit(cpuid, &cpu_online_map)) {
@@ -380,6 +381,7 @@
 	while (!atomic_read(&smp_commenced))
 		;
 
+	init_idle();
 	Dprintk("CPU %d is starting idle.\n", smp_processor_id());
 	return cpu_idle();
 }
@@ -416,11 +418,10 @@
 	if (!idle)
 		panic("No idle process for CPU %d", cpu);
 
-	task_set_cpu(idle, cpu);	/* we schedule the first task manually */
+	idle->cpu = cpu;
 
 	ia64_cpu_to_sapicid[cpu] = sapicid;
 
-	del_from_runqueue(idle);
 	unhash_process(idle);
 	init_tasks[cpu] = idle;
 
@@ -481,8 +482,7 @@
 	printk("Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
 
 	global_irq_holder = 0;
-	current->processor = 0;
-	init_idle();
+	current->cpu = 0;
 
 	/*
 	 * If SMP should be disabled, then really disable it!
arch/ia64/mm/fault.c +1 -2
diff -urN 2.4.17-O1/arch/ia64/mm/fault.c 2.4.17-O1-H7/arch/ia64/mm/fault.c
@@ -194,8 +194,7 @@
   out_of_memory:
 	up_read(&mm->mmap_sem);
 	if (current->pid == 1) {
-		current->policy |= SCHED_YIELD;
-		schedule();
+		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
arch/ia64/tools/print_offsets.c +1 -1
diff -urN 2.4.17-O1/arch/ia64/tools/print_offsets.c 2.4.17-O1-H7/arch/ia64/tools/print_offsets.c
@@ -54,7 +54,7 @@
     { "IA64_TASK_PTRACE_OFFSET",	offsetof (struct task_struct, ptrace) },
     { "IA64_TASK_SIGPENDING_OFFSET",	offsetof (struct task_struct, sigpending) },
     { "IA64_TASK_NEED_RESCHED_OFFSET",	offsetof (struct task_struct, need_resched) },
-    { "IA64_TASK_PROCESSOR_OFFSET",	offsetof (struct task_struct, processor) },
+    { "IA64_TASK_PROCESSOR_OFFSET",	offsetof (struct task_struct, cpu) },
     { "IA64_TASK_THREAD_OFFSET",	offsetof (struct task_struct, thread) },
     { "IA64_TASK_THREAD_KSP_OFFSET",	offsetof (struct task_struct, thread.ksp) },
 #ifdef CONFIG_PERFMON
include/asm-ia64/bitops.h +1 -0
diff -urN 2.4.17-O1/include/asm-ia64/bitops.h 2.4.17-O1-H7/include/asm-ia64/bitops.h
@@ -368,6 +368,7 @@
 
 #ifdef __KERNEL__
 
+#define __clear_bit(nr, addr)        clear_bit(nr, addr)
 #define ext2_set_bit                 test_and_set_bit
 #define ext2_clear_bit               test_and_clear_bit
 #define ext2_test_bit                test_bit
include/asm-ia64/mmu_context.h +1 -0
diff -urN 2.4.17-O1/include/asm-ia64/mmu_context.h 2.4.17-O1-H7/include/asm-ia64/mmu_context.h
@@ -118,6 +118,7 @@
 	reload_context(next);
 }
 
+#define sched_find_first_zero_bit(bitmap)      ffz(bitmap)
 #define switch_mm(prev_mm,next_mm,next_task,cpu)	activate_mm(prev_mm, next_mm)
 
 # endif /* ! __ASSEMBLY__ */
include/asm-ia64/smp.h +1 -7
diff -urN 2.4.17-O1/include/asm-ia64/smp.h 2.4.17-O1-H7/include/asm-ia64/smp.h
@@ -27,7 +27,7 @@
 #define SMP_IRQ_REDIRECTION	(1 << 0)
 #define SMP_IPI_REDIRECTION	(1 << 1)
 
-#define smp_processor_id()	(current->processor)
+#define smp_processor_id()	(current->cpu)
 
 extern struct smp_boot_data {
 	int cpu_count;
@@ -110,12 +110,6 @@
 
 #define NO_PROC_ID		0xffffffff	/* no processor magic marker */
 
-/*
- * Extra overhead to move a task from one cpu to another (due to TLB and cache misses).
- * Expressed in "negative nice value" units (larger number means higher priority/penalty).
- */
-#define PROC_CHANGE_PENALTY	20
-
 extern void __init init_smp_config (void);
 extern void smp_do_timer (struct pt_regs *regs);
 
kernel/printk.c +2 -0
diff -urN 2.4.17-O1/kernel/printk.c 2.4.17-O1-H7/kernel/printk.c
@@ -25,6 +25,8 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>			/* For in_interrupt() */
+#include <linux/config.h>
+#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 
kernel/sched.c +2 -0
diff -urN 2.4.17-O1/kernel/sched.c 2.4.17-O1-H7/kernel/sched.c
@@ -75,6 +75,8 @@
 #define unlock_task_rq(rq,p,flags)				\
 	spin_unlock_irqrestore(&rq->lock, flags)
 
+struct task_struct * init_tasks[NR_CPUS] = {&init_task, };
+
 /*
  * Adding/removing a task to/from a priority array:
  */
kernel/timer.c +6 -7
diff -urN 2.4.17-O1/kernel/timer.c 2.4.17-O1-H7/kernel/timer.c
@@ -585,17 +585,16 @@
 
 	update_one_process(p, user_tick, system, cpu);
 	if (p->pid) {
-		if (--p->counter <= 0) {
-			p->counter = 0;
-			p->need_resched = 1;
-		}
-		if (p->nice > 0)
+		if (p->__nice > 0)
 			kstat.per_cpu_nice[cpu] += user_tick;
 		else
 			kstat.per_cpu_user[cpu] += user_tick;
 		kstat.per_cpu_system[cpu] += system;
-	} else if (really_local_bh_count() || really_local_irq_count() > 1)
-		kstat.per_cpu_system[cpu] += system;
+	} else {
+		if (really_local_bh_count() || really_local_irq_count() > 1)
+			kstat.per_cpu_system[cpu] += system;
+	}
+	scheduler_tick(p);
 }
 
 /*
#3 lore raw
In reply to Nick Pollitt

What .config are you using? I grabbed the defconfig-bigsur-mp and compiled with your patch (had to disable DEVFS_DEBUG). The kernel doesn't get very far into the boot, less than a second, and it fails. Of course you said it would. But I couldn't get any useful info from the console so I ran the kernel in medusa.

In case you try this, it executes to about 15301000. Then it fails in acpi_hw_low_level_read. I also tried with the kernel patch I sent out Friday, which dies much sooner than this. But it's definitely not getting into schedule in my machine.

Did you config off other stuff (all the ACPI)?

Nick

Quoted 23 lines · Erich Focht

Hi,

I don't think that runqueues(cpu)->idle is set when you try to access it from head.S. It is much easier to reintroduce init_tasks and leave head.S as it is. Then no changes are needed in Ingo's patch for sched.h and sched.c. Ingo, could you please comment?

Please find attached an ia64 patch which should be applied over 2.4.17 + ia64 + sched-O1-2.4.17-H7.patch

It doesn't boot yet, the system (2CPU BigSur) crashes in
schedule() <- cpu_idle() <- rest_init() <- start_kernel()
Maybe somebody has an idea?

Thanks,

Erich

---
Erich Focht <[email protected]>
NEC European Supercomputer Systems, European HPC Technology Center

Signature · 3 lines
Nick Pollitt                                   phone: 650.933.7406
Scalable Linux Project                           fax: 650.932.0317
Silicon Graphics, Inc.                       [email protected]
#4 lore raw
In reply to Nick Pollitt

Hi Nick,

maybe the defconfig-bigsur-mp is a bit old, I could not find any definition of CONFIG_IA64_GRANULE_64MB or CONFIG_IA64_GRANULE_16MB which actually would mean that IA64_GRANULE_SIZE could be wrong. I attached a gzipped diff of the two configs, I had only minor changes to the default arch/ia64/defconfig. ACPI is definitely configured in.

Quoted 5 lines · Nick Pollitt

What .config are you using? I grabbed the defconfig-bigsur-mp and compiled with your patch (had to disable DEVFS_DEBUG). The kernel doesn't get very far into the boot, less than a second, and it fails. Of course you said it would. But I couldn't get any useful info from the console so I ran the kernel in medusa.

I don't have medusa and that's not free, I suppose...

Quoted 8 lines

In case you try this, it executes to about 15301000. Then it fails in acpi_hw_low_level_read. I also tried with the kernel patch I sent out Friday, which dies much sooner than this. But it's definitely not getting into schedule in my machine.

Did you config off other stuff (all the ACPI)?

Nick

Regards,

Erich

#5 lore raw
In reply to Nick Pollitt

Hi,

the appended patch almost does the job for IA64. On my BigSur 2.4.17 + ia64 + Ingo's_O(1)_I0 + ia64add.patch dies silently somewhere after init checked the filesystems, sometimes the last message beeing "INIT: Entering runlevel: 3" or "Mounting local filesystems:". When trying to boot with the "emergency" option added, it dies right after I enter the root password, but it doesn't always reach this point :-(

Any ideas what I should try to get some more insight?

Thanks,

Erich

arch/ia64/kernel/process.c +1 -5
diff -ur 2.4.17-ia64-kdb-o1/arch/ia64/kernel/process.c 2.4.17-ia64-kdb-O1-I0/arch/ia64/kernel/process.c
@@ -125,9 +125,6 @@
 cpu_idle (void *unused)
 {
 	/* endless idle loop with no priority at all */
-	init_idle();
-	current->nice = 20;
-	current->counter = -100;
 
 
 	while (1) {
@@ -136,11 +133,10 @@
 			min_xtp();
 #endif
 
-		while (!current->need_resched) {
+		if (!current->need_resched) {
 #ifdef CONFIG_IA64_SGI_SN
 			snidle();
 #endif
-			continue;
 		}
 
 #ifdef CONFIG_IA64_SGI_SN
arch/ia64/kernel/setup.c +3 -3
diff -ur 2.4.17-ia64-kdb-o1/arch/ia64/kernel/setup.c 2.4.17-ia64-kdb-O1-I0/arch/ia64/kernel/setup.c
@@ -375,10 +375,10 @@
 {
 #ifdef CONFIG_SMP
 #	define lpj	c->loops_per_jiffy
-#	define cpu	c->processor
+#	define cpum	c->processor
 #else
 #	define lpj	loops_per_jiffy
-#	define cpu	0
+#	define cpum	0
 #endif
 	char family[32], features[128], *cp;
 	struct cpuinfo_ia64 *c = v;
@@ -417,7 +417,7 @@
 		   "cpu MHz    : %lu.%06lu\n"
 		   "itc MHz    : %lu.%06lu\n"
 		   "BogoMIPS   : %lu.%02lu\n\n",
-		   cpu, c->vendor, family, c->model, c->revision, c->archrev,
+		   cpum, c->vendor, family, c->model, c->revision, c->archrev,
 		   features, c->ppn, c->number,
 		   c->proc_freq / 1000000, c->proc_freq % 1000000,
 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
arch/ia64/kernel/smp.c +6 -0
diff -ur 2.4.17-ia64-kdb-o1/arch/ia64/kernel/smp.c 2.4.17-ia64-kdb-O1-I0/arch/ia64/kernel/smp.c
@@ -196,6 +196,12 @@
 }
 
 void
+smp_send_reschedule_all(void)
+{
+	send_IPI_all(IA64_IPI_RESCHEDULE);
+}
+
+void
 smp_flush_tlb_all (void)
 {
 	smp_call_function ((void (*)(void *))__flush_tlb_all,0,1,1);
arch/ia64/kernel/smpboot.c +4 -5
diff -ur 2.4.17-ia64-kdb-o1/arch/ia64/kernel/smpboot.c 2.4.17-ia64-kdb-O1-I0/arch/ia64/kernel/smpboot.c
@@ -323,7 +323,7 @@
 	extern void perfmon_init_percpu(void);
 #endif
 
-	cpuid = smp_processor_id();
+	cpuid = cpu();
 	phys_id = hard_smp_processor_id();
 
 	if (test_and_set_bit(cpuid, &cpu_online_map)) {
@@ -380,6 +380,7 @@
 	while (!atomic_read(&smp_commenced))
 		;
 
+	init_idle();
 	Dprintk("CPU %d is starting idle.\n", smp_processor_id());
 	return cpu_idle();
 }
@@ -416,11 +417,10 @@
 	if (!idle)
 		panic("No idle process for CPU %d", cpu);
 
-	task_set_cpu(idle, cpu);	/* we schedule the first task manually */
+	idle->cpu = cpu;
 
 	ia64_cpu_to_sapicid[cpu] = sapicid;
 
-	del_from_runqueue(idle);
 	unhash_process(idle);
 	init_tasks[cpu] = idle;
 
@@ -481,8 +481,7 @@
 	printk("Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
 
 	global_irq_holder = 0;
-	current->processor = 0;
-	init_idle();
+	current->cpu = 0;
 
 	/*
 	 * If SMP should be disabled, then really disable it!
arch/ia64/mm/fault.c +1 -2
diff -ur 2.4.17-ia64-kdb-o1/arch/ia64/mm/fault.c 2.4.17-ia64-kdb-O1-I0/arch/ia64/mm/fault.c
@@ -194,8 +194,7 @@
   out_of_memory:
 	up_read(&mm->mmap_sem);
 	if (current->pid = 1) {
-		current->policy |= SCHED_YIELD;
-		schedule();
+		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
arch/ia64/tools/print_offsets.c +1 -1
diff -ur 2.4.17-ia64-kdb-o1/arch/ia64/tools/print_offsets.c 2.4.17-ia64-kdb-O1-I0/arch/ia64/tools/print_offsets.c
@@ -54,7 +54,7 @@
     { "IA64_TASK_PTRACE_OFFSET",	offsetof (struct task_struct, ptrace) },
     { "IA64_TASK_SIGPENDING_OFFSET",	offsetof (struct task_struct, sigpending) },
     { "IA64_TASK_NEED_RESCHED_OFFSET",	offsetof (struct task_struct, need_resched) },
-    { "IA64_TASK_PROCESSOR_OFFSET",	offsetof (struct task_struct, processor) },
+    { "IA64_TASK_PROCESSOR_OFFSET",	offsetof (struct task_struct, cpu) },
     { "IA64_TASK_THREAD_OFFSET",	offsetof (struct task_struct, thread) },
     { "IA64_TASK_THREAD_KSP_OFFSET",	offsetof (struct task_struct, thread.ksp) },
 #ifdef CONFIG_PERFMON
include/asm-ia64/bitops.h +1 -0
diff -ur 2.4.17-ia64-kdb-o1/include/asm-ia64/bitops.h 2.4.17-ia64-kdb-O1-I0/include/asm-ia64/bitops.h
@@ -368,6 +368,7 @@
 
 #ifdef __KERNEL__
 
+#define __clear_bit(nr, addr)        clear_bit(nr, addr)
 #define ext2_set_bit                 test_and_set_bit
 #define ext2_clear_bit               test_and_clear_bit
 #define ext2_test_bit                test_bit
include/asm-ia64/mmu_context.h +21 -0
diff -ur 2.4.17-ia64-kdb-o1/include/asm-ia64/mmu_context.h 2.4.17-ia64-kdb-O1-I0/include/asm-ia64/mmu_context.h
@@ -118,6 +118,27 @@
 	reload_context(next);
 }
 
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 168-bit bitmap where the first 128 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 168
+ * bits is cleared.
+ */
+#if MAX_RT_PRIO != 128 || MAX_PRIO != 173
+# error update this function.
+#endif
+
+static inline int sched_find_first_zero_bit(unsigned long *b)
+{
+	unsigned long rt;
+
+	rt = b[0] & b[1];
+	if (unlikely(rt != 0xffffffffffffffff))
+		return find_first_zero_bit(b, MAX_RT_PRIO);
+
+	return ffz(b[2]) + MAX_RT_PRIO;
+}
+
 #define switch_mm(prev_mm,next_mm,next_task,cpu)	activate_mm(prev_mm, next_mm)
 
 # endif /* ! __ASSEMBLY__ */
include/asm-ia64/smp.h +1 -7
diff -ur 2.4.17-ia64-kdb-o1/include/asm-ia64/smp.h 2.4.17-ia64-kdb-O1-I0/include/asm-ia64/smp.h
@@ -27,7 +27,7 @@
 #define SMP_IRQ_REDIRECTION	(1 << 0)
 #define SMP_IPI_REDIRECTION	(1 << 1)
 
-#define smp_processor_id()	(current->processor)
+#define smp_processor_id()	(current->cpu)
 
 extern struct smp_boot_data {
 	int cpu_count;
@@ -110,12 +110,6 @@
 
 #define NO_PROC_ID		0xffffffff	/* no processor magic marker */
 
-/*
- * Extra overhead to move a task from one cpu to another (due to TLB and cache misses).
- * Expressed in "negative nice value" units (larger number means higher priority/penalty).
- */
-#define PROC_CHANGE_PENALTY	20
-
 extern void __init init_smp_config (void);
 extern void smp_do_timer (struct pt_regs *regs);
 
kdb/kdbmain.c +2 -1
diff -ur 2.4.17-ia64-kdb-o1/kdb/kdbmain.c 2.4.17-ia64-kdb-O1-I0/kdb/kdbmain.c
@@ -2349,6 +2349,7 @@
  * Remarks:
  */
 
+#define task_has_cpu(p) 1
 int
 kdb_ps(int argc, const char **argv, const char **envp, struct pt_regs *regs)
 {
@@ -2360,7 +2361,7 @@
 	for_each_task(p) {
 		kdb_printf("0x%p %08d %08d  %1.1d  %3.3d  %s  0x%p%c%s\n",
 			   (void *)p, p->pid, p->p_pptr->pid,
-			   task_has_cpu(p), p->processor,
+			   task_has_cpu(p), p->cpu,
 			   (p->state = 0)?"run ":(p->state>0)?"stop":"unrn",
 			   (void *)(&p->thread),
 			   (p = current) ? '*': ' ',
kernel/printk.c +2 -0
diff -ur 2.4.17-ia64-kdb-o1/kernel/printk.c 2.4.17-ia64-kdb-O1-I0/kernel/printk.c
@@ -25,6 +25,8 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>			/* For in_interrupt() */
+#include <linux/config.h>
+#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 
kernel/sched.c +2 -0
diff -ur 2.4.17-ia64-kdb-o1/kernel/sched.c 2.4.17-ia64-kdb-O1-I0/kernel/sched.c
@@ -75,6 +75,8 @@
 #define unlock_task_rq(rq,p,flags)				\
 	spin_unlock_irqrestore(&rq->lock, flags)
 
+struct task_struct * init_tasks[NR_CPUS] __initdata = {&init_task, };
+
 /*
  * Adding/removing a task to/from a priority array:
  */
kernel/timer.c +6 -7
diff -ur 2.4.17-ia64-kdb-o1/kernel/timer.c 2.4.17-ia64-kdb-O1-I0/kernel/timer.c
@@ -585,17 +585,16 @@
 
 	update_one_process(p, user_tick, system, cpu);
 	if (p->pid) {
-		if (--p->counter <= 0) {
-			p->counter = 0;
-			p->need_resched = 1;
-		}
-		if (p->nice > 0)
+		if (p->__nice > 0)
 			kstat.per_cpu_nice[cpu] += user_tick;
 		else
 			kstat.per_cpu_user[cpu] += user_tick;
 		kstat.per_cpu_system[cpu] += system;
-	} else if (really_local_bh_count() || really_local_irq_count() > 1)
-		kstat.per_cpu_system[cpu] += system;
+	} else {
+		if (really_local_bh_count() || really_local_irq_count() > 1)
+			kstat.per_cpu_system[cpu] += system;
+	}
+	scheduler_tick(p);
 }
 
 /*
#7 lore raw
In reply to Nick Pollitt
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

is this with 1 CPU?

no, it's with 2 CPUs. Does it make sense to try without CONFIG_SMP?

yes, UP scheduling is much simpler.

When booting with maxcpus=1 it died after:
...
Bringing up interface eth0: [ OK ]

With nosmp it died after
...
Enabling swap space: [ OK ]

I recompiled with CONFIG_SMP unset (needed only to put one line into #ifdefs) and this (UP) version works. So there isn't anything fundamentally wrong. I'll try running with CONFIG_DEBUG_SPINLOCK and CONFIG_IA64_DEBUG_IRQ...

Regards,
Erich

#8 lore raw
In reply to Nick Pollitt
Quoted 6 lines · Erich Focht

the appended patch almost does the job for IA64. On my BigSur 2.4.17 + ia64 + Ingo's_O(1)_I0 + ia64add.patch dies silently somewhere after init checked the filesystems, sometimes the last message beeing "INIT:
Entering runlevel: 3" or "Mounting local filesystems:". When trying to boot with the "emergency" option added, it dies right after I enter the root password, but it doesn't always reach this point :-(

is this with 1 CPU?

Ingo

#9 lore raw
In reply to Nick Pollitt
Quoted 3 lines · Erich Focht
Quoted 1 line

is this with 1 CPU?

no, it's with 2 CPUs. Does it make sense to try without CONFIG_SMP?

yes, UP scheduling is much simpler.

Ingo

#10 lore raw
In reply to Nick Pollitt
Quoted 3 lines · Ingo Molnar
Quoted 1 line

no, it's with 2 CPUs. Does it make sense to try without CONFIG_SMP?

yes, UP scheduling is much simpler.

that having said, i've implemented & tested the O(1) scheduler purely on SMP. But the UP port took about 5 minutes, and the UP kernel worked on the first bootup. In your case it might make sense to first test UP and then go over to SMP. If there is some fundamental problem it's much easier to debug & fix it on UP.

Ingo

#11 lore raw
In reply to Nick Pollitt
Quoted 8 lines · Erich Focht

Hi,

the appended patch almost does the job for IA64. On my BigSur 2.4.17 + ia64 + Ingo's_O(1)_I0 + ia64add.patch dies silently somewhere after init checked the filesystems, sometimes the last message beeing "INIT: Entering runlevel: 3" or "Mounting local filesystems:". When trying to boot with the "emergency" option added, it dies right after I enter the root password, but it doesn't always reach this point :-(

With this patch I can boot UP, log in, etc. I get did one compile error in arch/ia64/kernel/setup.c, saying that the structure 'c' didn't have a member named 'processor' - sure looks like it does to me.

Did this patch work for you in the UP case? If not I suspect our hardware may be slightly different. I'll attach my config just in case. I'll try SMP tomorrow - getting late here.

Nick

#
# Automatically generated make config: don't edit
#

#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y

#
# Loadable module support
#
CONFIG_MODULES=y
# CONFIG_MODVERSIONS is not set
CONFIG_KMOD=y

#
# General setup
#
CONFIG_IA64=y
# CONFIG_ISA is not set
# CONFIG_EISA is not set
# CONFIG_MCA is not set
# CONFIG_SBUS is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_ACPI=y
CONFIG_ACPI_EFI=y
CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_KERNEL_CONFIG=y
CONFIG_ITANIUM=y
# CONFIG_MCKINLEY is not set
# CONFIG_IA64_GENERIC is not set
CONFIG_IA64_DIG=y
# CONFIG_IA64_HP_SIM is not set
# CONFIG_IA64_SGI_SN1 is not set
# CONFIG_IA64_SGI_SN2 is not set
# CONFIG_IA64_PAGE_SIZE_4KB is not set
# CONFIG_IA64_PAGE_SIZE_8KB is not set
CONFIG_IA64_PAGE_SIZE_16KB=y
# CONFIG_IA64_PAGE_SIZE_64KB is not set
CONFIG_IA64_BRL_EMU=y
# CONFIG_ITANIUM_BSTEP_SPECIFIC is not set
CONFIG_IA64_L1_CACHE_SHIFT=6
CONFIG_IA64_MCA=y
CONFIG_PM=y
CONFIG_KCORE_ELF=y
# CONFIG_SMP is not set
CONFIG_IA32_SUPPORT=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
CONFIG_EFI_VARS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_ACPI_DEBUG is not set
# CONFIG_ACPI_BUSMGR is not set
# CONFIG_ACPI_SYS is not set
# CONFIG_ACPI_CPU is not set
# CONFIG_ACPI_BUTTON is not set
# CONFIG_ACPI_AC is not set
# CONFIG_ACPI_EC is not set
# CONFIG_ACPI_CMBATT is not set
# CONFIG_ACPI_THERMAL is not set
CONFIG_PCI=y
CONFIG_PCI_NAMES=y
# CONFIG_HOTPLUG is not set
# CONFIG_PCMCIA is not set

#
# Parallel port support
#
# CONFIG_PARPORT is not set

#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_NETLINK_DEV=y
# CONFIG_NETFILTER is not set
CONFIG_FILTER=y
CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
# CONFIG_VLAN_8021Q is not set

#
#
#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_LLC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set

#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set

#
# Memory Technology Devices (MTD)
#
# CONFIG_MTD is not set

#
# Plug and Play configuration
#
# CONFIG_PNP is not set
# CONFIG_ISAPNP is not set

#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y

#
# I2O device support
#
# CONFIG_I2O is not set
# CONFIG_I2O_PCI is not set
# CONFIG_I2O_BLOCK is not set
# CONFIG_I2O_LAN is not set
# CONFIG_I2O_SCSI is not set
# CONFIG_I2O_PROC is not set

#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
# CONFIG_MD_RAID0 is not set
# CONFIG_MD_RAID1 is not set
# CONFIG_MD_RAID5 is not set
# CONFIG_MD_MULTIPATH is not set
# CONFIG_BLK_DEV_LVM is not set

#
# ATA/IDE/MFM/RLL support
#
CONFIG_IDE=y

#
# IDE, ATA and ATAPI Block devices
#
CONFIG_BLK_DEV_IDE=y

#
# Please see Documentation/ide.txt for help/info on IDE drives #
# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
# CONFIG_BLK_DEV_IDEDISK_IBM is not set
# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
# CONFIG_BLK_DEV_IDEDISK_WD is not set
# CONFIG_BLK_DEV_COMMERIAL is not set
# CONFIG_BLK_DEV_TIVO is not set
# CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y
CONFIG_BLK_DEV_IDESCSI=y

#
# IDE chipset support/bugfixes
#
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
# CONFIG_BLK_DEV_ISAPNP is not set
# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_IDEDMA_PCI_AUTO is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_AEC62XX_TUNING is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
# CONFIG_AMD74XX_OVERRIDE is not set
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_HPT34X_AUTODMA is not set
# CONFIG_BLK_DEV_HPT366 is not set
CONFIG_BLK_DEV_PIIX=y
# CONFIG_PIIX_TUNING is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_PDC202XX is not set
# CONFIG_PDC202XX_BURST is not set
# CONFIG_PDC202XX_FORCE is not set
# CONFIG_BLK_DEV_SVWKS is not set
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_IDEDMA_IVB is not set
# CONFIG_DMA_NONPCI is not set
CONFIG_BLK_DEV_IDE_MODES=y
# CONFIG_BLK_DEV_ATARAID is not set
# CONFIG_BLK_DEV_ATARAID_PDC is not set
# CONFIG_BLK_DEV_ATARAID_HPT is not set

#
# SCSI support
#
CONFIG_SCSI=y

#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
# CONFIG_CHR_DEV_SG is not set

#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs #
CONFIG_SCSI_DEBUG_QUEUES=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y

#
# SCSI low-level drivers
#
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_7000FASST is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AHA1740 is not set
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_CPQFCTS is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_NCR53C8XX is not set
# CONFIG_SCSI_SYM53C8XX is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
CONFIG_SCSI_QLOGIC_1280=y
# CONFIG_SCSI_QLOGIC_QLA2100 is not set
# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_DEBUG is not set

#
# Network device support
#
CONFIG_NETDEVICES=y

#
# ARCnet devices
#
# CONFIG_ARCNET is not set
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set

#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
# CONFIG_SUNLANCE is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNBMAC is not set
# CONFIG_SUNQE is not set
# CONFIG_SUNLANCE is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_HP100 is not set
# CONFIG_NET_ISA is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
# CONFIG_TULIP is not set
# CONFIG_DE4X5 is not set
# CONFIG_DGRS is not set
# CONFIG_DM9102 is not set
CONFIG_EEPRO100=y
# CONFIG_LNE390 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
# CONFIG_NE3210 is not set
# CONFIG_ES3210 is not set
# CONFIG_8139CP is not set
# CONFIG_8139TOO is not set
# CONFIG_8139TOO_PIO is not set
# CONFIG_8139TOO_TUNE_TWISTER is not set
# CONFIG_8139TOO_8129 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_VIA_RHINE_MMIO is not set
# CONFIG_WINBOND_840 is not set
# CONFIG_NET_POCKET is not set

#
# Ethernet (1000 Mbit)
#
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PLIP is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set

#
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set

#
# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
# CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set

#
# Wan interfaces
#
# CONFIG_WAN is not set

#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set

#
# ISDN subsystem
#
# CONFIG_ISDN is not set

#
# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) #
# CONFIG_CD_NO_IDESCSI is not set

#
# Input core support
#
CONFIG_INPUT=y
CONFIG_INPUT_KEYBDEV=y
CONFIG_INPUT_MOUSEDEV=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
CONFIG_INPUT_EVDEV=y

#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_SERIAL_CONSOLE=y
# CONFIG_SERIAL_ACPI is not set
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=256

#
# I2C support
#
# CONFIG_I2C is not set

#
# Mice
#
# CONFIG_BUSMOUSE is not set
CONFIG_MOUSE=y
CONFIG_PSMOUSE=y
# CONFIG_82C710_MOUSE is not set
# CONFIG_PC110_PAD is not set

#
# Joysticks
#
# CONFIG_INPUT_GAMEPORT is not set
# CONFIG_INPUT_NS558 is not set
# CONFIG_INPUT_LIGHTNING is not set
# CONFIG_INPUT_PCIGAME is not set
# CONFIG_INPUT_CS461X is not set
# CONFIG_INPUT_EMU10K1 is not set
# CONFIG_INPUT_SERIO is not set
# CONFIG_INPUT_SERPORT is not set

#
# Joysticks
#
# CONFIG_INPUT_ANALOG is not set
# CONFIG_INPUT_A3D is not set
# CONFIG_INPUT_ADI is not set
# CONFIG_INPUT_COBRA is not set
# CONFIG_INPUT_GF2K is not set
# CONFIG_INPUT_GRIP is not set
# CONFIG_INPUT_INTERACT is not set
# CONFIG_INPUT_TMDC is not set
# CONFIG_INPUT_SIDEWINDER is not set
# CONFIG_INPUT_IFORCE_USB is not set
# CONFIG_INPUT_IFORCE_232 is not set
# CONFIG_INPUT_WARRIOR is not set
# CONFIG_INPUT_MAGELLAN is not set
# CONFIG_INPUT_SPACEORB is not set
# CONFIG_INPUT_SPACEBALL is not set
# CONFIG_INPUT_STINGER is not set
# CONFIG_INPUT_DB9 is not set
# CONFIG_INPUT_GAMECON is not set
# CONFIG_INPUT_TURBOGRAFX is not set
# CONFIG_QIC02_TAPE is not set

#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
CONFIG_EFI_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set

#
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
# CONFIG_AGP is not set
# CONFIG_DRM is not set

#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set

#
# File systems
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_ADFS_FS is not set
# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_JBD is not set
# CONFIG_JBD_DEBUG is not set
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_UMSDOS_FS is not set
CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_TMPFS is not set
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
# CONFIG_ZISOFS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
CONFIG_DEVFS_MOUNT=y
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
# CONFIG_UDF_FS is not set
# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
# CONFIG_UFS_FS_WRITE is not set

#
# Network File Systems
#
# CONFIG_CODA_FS is not set
# CONFIG_INTERMEZZO_FS is not set
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=y
CONFIG_NFSD_V3=y
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
# CONFIG_NCPFS_PACKET_SIGNING is not set
# CONFIG_NCPFS_IOCTL_LOCKING is not set
# CONFIG_NCPFS_STRONG is not set
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
# CONFIG_ZISOFS_FS is not set
# CONFIG_ZLIB_FS_INFLATE is not set

#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
# CONFIG_SMB_NLS is not set
CONFIG_NLS=y

#
# Native Language Support
#
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
# CONFIG_NLS_CODEPAGE_850 is not set
# CONFIG_NLS_CODEPAGE_852 is not set
# CONFIG_NLS_CODEPAGE_855 is not set
# CONFIG_NLS_CODEPAGE_857 is not set
# CONFIG_NLS_CODEPAGE_860 is not set
# CONFIG_NLS_CODEPAGE_861 is not set
# CONFIG_NLS_CODEPAGE_862 is not set
# CONFIG_NLS_CODEPAGE_863 is not set
# CONFIG_NLS_CODEPAGE_864 is not set
# CONFIG_NLS_CODEPAGE_865 is not set
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_936 is not set
# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_CODEPAGE_932 is not set
# CONFIG_NLS_CODEPAGE_949 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
# CONFIG_NLS_ISO8859_5 is not set
# CONFIG_NLS_ISO8859_6 is not set
# CONFIG_NLS_ISO8859_7 is not set
# CONFIG_NLS_ISO8859_9 is not set
# CONFIG_NLS_ISO8859_13 is not set
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set

#
# Console drivers
#
CONFIG_VGA_CONSOLE=y

#
# Frame-buffer support
#
# CONFIG_FB is not set

#
# Sound
#
# CONFIG_SOUND is not set

#
# USB support
#
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set

#
# Miscellaneous USB options
#
# CONFIG_USB_DEVICEFS is not set
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_LONG_TIMEOUT is not set

#
# USB Controllers
#
# CONFIG_USB_UHCI is not set
# CONFIG_USB_UHCI_ALT is not set
# CONFIG_USB_OHCI is not set

#
# USB Device Class drivers
#
# CONFIG_USB_AUDIO is not set
# CONFIG_USB_BLUETOOTH is not set
# CONFIG_USB_STORAGE is not set
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_HP8200e is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set

#
# USB Human Interface Devices (HID)
#
# CONFIG_USB_HID is not set
# CONFIG_USB_HIDDEV is not set
# CONFIG_USB_KBD is not set
# CONFIG_USB_MOUSE is not set
# CONFIG_USB_WACOM is not set

#
# USB Imaging devices
#
# CONFIG_USB_DC2XX is not set
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_SCANNER is not set
# CONFIG_USB_MICROTEK is not set
# CONFIG_USB_HPUSBSCSI is not set

#
# USB Multimedia devices
#

#
# Video4Linux support is needed for USB Multimedia device support
#

#
# USB Network adaptors
#
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_CATC is not set
# CONFIG_USB_CDCETHER is not set
# CONFIG_USB_USBNET is not set

#
# USB port drivers
#
# CONFIG_USB_USS720 is not set

#
# USB Serial Converter support
#
# CONFIG_USB_SERIAL is not set
# CONFIG_USB_SERIAL_GENERIC is not set
# CONFIG_USB_SERIAL_BELKIN is not set
# CONFIG_USB_SERIAL_WHITEHEAT is not set
# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
# CONFIG_USB_SERIAL_VISOR is not set
# CONFIG_USB_SERIAL_IR is not set
# CONFIG_USB_SERIAL_EDGEPORT is not set
# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
# CONFIG_USB_SERIAL_KEYSPAN is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
# CONFIG_USB_SERIAL_PL2303 is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OMNINET is not set

#
# USB Miscellaneous drivers
#
# CONFIG_USB_RIO500 is not set

#
# Bluetooth support
#
# CONFIG_BLUEZ is not set

#
# Kernel hacking
#
# CONFIG_IA64_GRANULE_16MB is not set
CONFIG_IA64_GRANULE_64MB=y
CONFIG_DEBUG_KERNEL=y
CONFIG_IA64_PRINT_HAZARDS=y
# CONFIG_DISABLE_VHPT is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_IA64_EARLY_PRINTK=y
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_IA64_DEBUG_CMPXCHG is not set
# CONFIG_IA64_DEBUG_IRQ is not set

#12 lore raw
In reply to Nick Pollitt
Quoted 9 lines · Nick Pollitt

With this patch I can boot UP, log in, etc. I get did one compile error in arch/ia64/kernel/setup.c, saying that the structure 'c' didn't have a member named 'processor' - sure looks like it does to me.

Did this patch work for you in the UP case? If not I suspect our hardware may be slightly different. I'll attach my config just in case. I'll try SMP tomorrow - getting late here.

Nick

I also needed an additional #ifdef CONFIG_SMP in setup.c around the line which assigns c->processor = cpu(). So I guess our hardware is similar. Can you reproduce the hang on the simulator?

Erich

#13 lore raw
In reply to Nick Pollitt

In case you're still fighting with Ingo's scheduler on 2.4.xx, you might want to try the attached patch. It's a gross hack to work around a race condition in set_cpus_allowed(). Without this hack, the kernel would almost always die as soon as it tried to migrate ksoftirqd_CPU1 from CPU 0 to CPU 1. With the patch, it boots up to the point where the serial line driver gets initialized, which is progress, I suppose.

The fundamental problem is that current set_cpus_allowed() lets the same task run on two CPUs for a brief period of time. This violates scheduling assumptions made by the kernel and hence results in race conditions.

	--david
kernel/sched.c +5 -4
@@ -230,7 +230,7 @@
 	spin_unlock_irq(&this_rq()->lock);
 }
 
-static inline void context_switch(task_t *prev, task_t *next)
+static inline void context_switch(task_t *prev, task_t *next, int dont_clear)
 {
 	struct mm_struct *mm = next->mm;
 	struct mm_struct *oldmm = prev->active_mm;
@@ -245,7 +245,8 @@
 		switch_mm(oldmm, mm, next, smp_processor_id());
 
 	if (!prev->mm) {
-		prev->active_mm = NULL;
+		if (!dont_clear)
+			prev->active_mm = NULL;
 		mmdrop(oldmm);
 	}
 
@@ -519,7 +520,7 @@
 		rq->nr_switches++;
 		rq->curr = next;
 		next->cpu = prev->cpu;
-		context_switch(prev, next);
+		context_switch(prev, next, 0);
 		/*
 		 * The runqueue pointer might be from another CPU
 		 * if the new task was last running on a different
@@ -721,7 +722,7 @@
 	this_rq->nr_switches++;
 	this_rq->curr = this_rq->idle;
 	this_rq->idle->need_resched = 1;
-	context_switch(current, this_rq->idle);
+	context_switch(current, this_rq->idle, 1);
 	barrier();
 	spin_unlock_irq(&this_rq()->lock);
 }
#14 lore raw
In reply to Nick Pollitt

With this hack, I'm getting an SMP boot all the way to the init script 'Checking for new Hardware [OK]' before the hang.

This patch is against linux+ia64+ingoJ0.

Nick

Quoted 8 lines · David Mosberger

In case you're still fighting with Ingo's scheduler on 2.4.xx, you might want to try the attached patch. It's a gross hack to work around a race condition in set_cpus_allowed(). Without this hack, the kernel would almost always die as soon as it tried to migrate ksoftirqd_CPU1 from CPU 0 to CPU 1. With the patch, it boots up to the point where the serial line driver gets initialized, which is progress, I suppose.

Quoted 6 lines

The fundamental problem is that current set_cpus_allowed() lets the same task run on two CPUs for a brief period of time. This violates scheduling assumptions made by the kernel and hence results in race conditions.

	--david
arch/ia64/kernel/process.c +1 -5
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/arch/ia64/kernel/process.c mylinux/arch/ia64/kernel/process.c
@@ -125,9 +125,6 @@
 cpu_idle (void *unused)
 {
 	/* endless idle loop with no priority at all */
-	init_idle();
-	current->nice = 20;
-	current->counter = -100;
 
 
 	while (1) {
@@ -136,11 +133,10 @@
 			min_xtp();
 #endif
 
-		while (!current->need_resched) {
+		if (!current->need_resched) {
 #ifdef CONFIG_IA64_SGI_SN
 			snidle();
 #endif
-			continue;
 		}
 
 #ifdef CONFIG_IA64_SGI_SN
arch/ia64/kernel/setup.c +3 -3
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/arch/ia64/kernel/setup.c mylinux/arch/ia64/kernel/setup.c
@@ -375,10 +375,10 @@
 {
 #ifdef CONFIG_SMP
 #	define lpj	c->loops_per_jiffy
-#	define cpu	c->processor
+#	define cpum	c->processor
 #else
 #	define lpj	loops_per_jiffy
-#	define cpu	0
+#	define cpum	0
 #endif
 	char family[32], features[128], *cp;
 	struct cpuinfo_ia64 *c = v;
@@ -417,7 +417,7 @@
 		   "cpu MHz    : %lu.%06lu\n"
 		   "itc MHz    : %lu.%06lu\n"
 		   "BogoMIPS   : %lu.%02lu\n\n",
-		   cpu, c->vendor, family, c->model, c->revision, c->archrev,
+		   cpum, c->vendor, family, c->model, c->revision, c->archrev,
 		   features, c->ppn, c->number,
 		   c->proc_freq / 1000000, c->proc_freq % 1000000,
 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
arch/ia64/kernel/smp.c +23 -0
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/arch/ia64/kernel/smp.c mylinux/arch/ia64/kernel/smp.c
@@ -186,6 +186,29 @@
 }
 
 void
+smp_send_reschedule_all(void)
+{
+	send_IPI_all(IA64_IPI_RESCHEDULE);
+}
+
+static spinlock_t migration_lock = SPIN_LOCK_UNLOCKED;
+static task_t *new_task;
+
+/*
+ * This function sends a 'task migration' IPI to another CPU.
+ * Must be called from syscall contexts, with interrupts *enabled*.
+ */
+void smp_migrate_task(int cpu, task_t *p)
+{
+	/*
+	 * The target CPU will unlock the migration spinlock:
+	 */
+	spin_lock(&migration_lock);
+	new_task = p;
+	smp_send_reschedule(cpu);
+}
+
+void
 smp_flush_tlb_all (void)
 {
 	smp_call_function ((void (*)(void *))__flush_tlb_all,0,1,1);
arch/ia64/kernel/smpboot.c +4 -5
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/arch/ia64/kernel/smpboot.c mylinux/arch/ia64/kernel/smpboot.c
@@ -323,7 +323,7 @@
 	extern void perfmon_init_percpu(void);
 #endif
 
-	cpuid = smp_processor_id();
+	cpuid = cpu();
 	phys_id = hard_smp_processor_id();
 
 	if (test_and_set_bit(cpuid, &cpu_online_map)) {
@@ -380,6 +380,7 @@
 	while (!atomic_read(&smp_commenced))
 		;
 
+	init_idle();
 	Dprintk("CPU %d is starting idle.\n", smp_processor_id());
 	return cpu_idle();
 }
@@ -416,11 +417,10 @@
 	if (!idle)
 		panic("No idle process for CPU %d", cpu);
 
-	task_set_cpu(idle, cpu);	/* we schedule the first task manually */
+	idle->cpu = cpu;
 
 	ia64_cpu_to_sapicid[cpu] = sapicid;
 
-	del_from_runqueue(idle);
 	unhash_process(idle);
 	init_tasks[cpu] = idle;
 
@@ -481,8 +481,7 @@
 	printk("Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
 
 	global_irq_holder = 0;
-	current->processor = 0;
-	init_idle();
+	current->cpu = 0;
 
 	/*
 	 * If SMP should be disabled, then really disable it!
arch/ia64/mm/fault.c +1 -2
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/arch/ia64/mm/fault.c mylinux/arch/ia64/mm/fault.c
@@ -194,8 +194,7 @@
   out_of_memory:
 	up_read(&mm->mmap_sem);
 	if (current->pid == 1) {
-		current->policy |= SCHED_YIELD;
-		schedule();
+		yield();
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
arch/ia64/tools/print_offsets.c +1 -1
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/arch/ia64/tools/print_offsets.c mylinux/arch/ia64/tools/print_offsets.c
@@ -54,7 +54,7 @@
     { "IA64_TASK_PTRACE_OFFSET",	offsetof (struct task_struct, ptrace) },
     { "IA64_TASK_SIGPENDING_OFFSET",	offsetof (struct task_struct, sigpending) },
     { "IA64_TASK_NEED_RESCHED_OFFSET",	offsetof (struct task_struct, need_resched) },
-    { "IA64_TASK_PROCESSOR_OFFSET",	offsetof (struct task_struct, processor) },
+    { "IA64_TASK_PROCESSOR_OFFSET",	offsetof (struct task_struct, cpu) },
     { "IA64_TASK_THREAD_OFFSET",	offsetof (struct task_struct, thread) },
     { "IA64_TASK_THREAD_KSP_OFFSET",	offsetof (struct task_struct, thread.ksp) },
 #ifdef CONFIG_PERFMON
include/asm-ia64/bitops.h +1 -0
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/include/asm-ia64/bitops.h mylinux/include/asm-ia64/bitops.h
@@ -368,6 +368,7 @@
 
 #ifdef __KERNEL__
 
+#define __clear_bit(nr, addr)        clear_bit(nr, addr)
 #define ext2_set_bit                 test_and_set_bit
 #define ext2_clear_bit               test_and_clear_bit
 #define ext2_test_bit                test_bit
include/asm-ia64/mmu_context.h +21 -0
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/include/asm-ia64/mmu_context.h mylinux/include/asm-ia64/mmu_context.h
@@ -118,6 +118,27 @@
 	reload_context(next);
 }
 
+/*
+ * Every architecture must define this function. It's the fastest
+ * way of searching a 168-bit bitmap where the first 128 bits are
+ * unlikely to be set. It's guaranteed that at least one of the 168
+ * bits is cleared.
+ */
+#if MAX_RT_PRIO != 128 || MAX_PRIO != 173
+/* # error update this function. */
+#endif
+
+static inline int sched_find_first_zero_bit(unsigned long *b)
+{
+	unsigned long rt;
+
+	rt = b[0] & b[1];
+	if (unlikely(rt != 0xffffffffffffffff))
+		return find_first_zero_bit(b, MAX_RT_PRIO);
+
+	return ffz(b[2]) + MAX_RT_PRIO;
+}
+
 #define switch_mm(prev_mm,next_mm,next_task,cpu)	activate_mm(prev_mm, next_mm)
 
 # endif /* ! __ASSEMBLY__ */
include/asm-ia64/smp.h +4 -7
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/include/asm-ia64/smp.h mylinux/include/asm-ia64/smp.h
@@ -27,7 +27,7 @@
 #define SMP_IRQ_REDIRECTION	(1 << 0)
 #define SMP_IPI_REDIRECTION	(1 << 1)
 
-#define smp_processor_id()	(current->processor)
+#define smp_processor_id()	(current->cpu)
 
 extern struct smp_boot_data {
 	int cpu_count;
@@ -48,6 +48,9 @@
 
 extern unsigned long ap_wakeup_vector;
 
+extern void smp_send_reschedule(int cpu);
+extern void smp_send_reschedule_all(void);
+
 /*
  * Function to map hard smp processor id to logical id.  Slow, so
  * don't use this in performance-critical code.
@@ -109,12 +112,6 @@
 }
 
 #define NO_PROC_ID		0xffffffff	/* no processor magic marker */
-
-/*
- * Extra overhead to move a task from one cpu to another (due to TLB and cache misses).
- * Expressed in "negative nice value" units (larger number means higher priority/penalty).
- */
-#define PROC_CHANGE_PENALTY	20
 
 extern void __init init_smp_config (void);
 extern void smp_do_timer (struct pt_regs *regs);
include/linux/smp.h +0 -6
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/include/linux/smp.h mylinux/include/linux/smp.h
@@ -24,12 +24,6 @@
 extern void smp_send_stop(void);
 
 /*
- * sends a 'reschedule' event to another CPU:
- */
-extern void FASTCALL(smp_send_reschedule(int cpu));
-
-
-/*
  * Boot processor call to load the other CPU's
  */
 extern void smp_boot_cpus(void);
kernel/printk.c +2 -0
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/kernel/printk.c mylinux/kernel/printk.c
@@ -25,6 +25,8 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>			/* For in_interrupt() */
+#include <linux/config.h>
+#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 
kernel/sched.c +6 -3
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/kernel/sched.c mylinux/kernel/sched.c
@@ -94,6 +94,8 @@
 	p->array = array;
 }
 
+struct task_struct * init_tasks[NR_CPUS] __initdata = {&init_task, };
+
 /*
  * A task is 'heavily interactive' if it has reached the
  * bottom 25% of the SCHED_OTHER priority range - in this
@@ -275,7 +277,7 @@
 	spin_unlock_irq(&this_rq()->lock);
 }
 
-static inline void context_switch(task_t *prev, task_t *next)
+static inline void context_switch(task_t *prev, task_t *next, int dont_clear)
 {
 	struct mm_struct *mm = next->mm;
 	struct mm_struct *oldmm = prev->active_mm;
@@ -290,7 +292,8 @@
 		switch_mm(oldmm, mm, next, smp_processor_id());
 
 	if (!prev->mm) {
-		prev->active_mm = NULL;
+		if (!dont_clear)
+			prev->active_mm = NULL;
 		mmdrop(oldmm);
 	}
 
@@ -614,7 +617,7 @@
 	if (likely(prev != next)) {
 		rq->nr_switches++;
 		rq->curr = next;
-		context_switch(prev, next);
+		context_switch(prev, next, 0);
 		/*
 		 * The runqueue pointer might be from another CPU
 		 * if the new task was last running on a different
kernel/timer.c +6 -7
diff -X /home/npollitt/dontdiff -Nur ingoj0.2/kernel/timer.c mylinux/kernel/timer.c
@@ -585,17 +585,16 @@
 
 	update_one_process(p, user_tick, system, cpu);
 	if (p->pid) {
-		if (--p->counter <= 0) {
-			p->counter = 0;
-			p->need_resched = 1;
-		}
-		if (p->nice > 0)
+		if (p->__nice > 0)
 			kstat.per_cpu_nice[cpu] += user_tick;
 		else
 			kstat.per_cpu_user[cpu] += user_tick;
 		kstat.per_cpu_system[cpu] += system;
-	} else if (really_local_bh_count() || really_local_irq_count() > 1)
-		kstat.per_cpu_system[cpu] += system;
+	} else {
+		if (really_local_bh_count() || really_local_irq_count() > 1)
+			kstat.per_cpu_system[cpu] += system;
+	}
+	sched_tick(p);
 }
 
 /*
#15 lore raw
In reply to Nick Pollitt
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Ingo Molnar

Ingo> Every architecture has to define the following function:

  Ingo>      extern void smp_migrate_task(int cpu, task_t *task);

Ingo> the lowlevel code has to pass the 'task' pointer over to the Ingo> target CPU. (architectures that can send information in Ingo> cross-CPU messages can send it over directly - in the x86 case Ingo> it's done similarly to smp_call_function().)

That sounds much better.

Thanks,

	--david
#16 lore raw
In reply to Nick Pollitt
Quoted 4 lines · David Mosberger

The fundamental problem is that current set_cpus_allowed() lets the same task run on two CPUs for a brief period of time. This violates scheduling assumptions made by the kernel and hence results in race conditions.

i've fixed this in -J0 already, without adding overhead to the scheduler hotpath. I've added better task-migration code as well. Every architecture has to define the following function:

     extern void smp_migrate_task(int cpu, task_t *task);

the lowlevel code has to pass the 'task' pointer over to the target CPU. (architectures that can send information in cross-CPU messages can send it over directly - in the x86 case it's done similarly to smp_call_function().)

Ingo

#17 lore raw
In reply to Nick Pollitt
Quoted 2 lines · Nick Pollitt

With this hack, I'm getting an SMP boot all the way to the init script 'Checking for new Hardware [OK]' before the hang.

i'd suggest to remove the dont_clear thing from sched.c, unless there are other reasons to it, apart from working around the task migration bug.

Ingo

#18 lore raw
In reply to Nick Pollitt

Hmm, doesn't work, yet with 2.4.17 :-(

There must be some path where a rq->lock remains set, with some sort of print-eip-like tool I see lockups with

load_balance  vs.   __wake_up
__wake_up     vs.   sched_tick

etc...

Tomorrow I'll try 2.5.2.

Regards,
Erich

Quoted 14 lines · David Mosberger

In case you're still fighting with Ingo's scheduler on 2.4.xx, you might want to try the attached patch. It's a gross hack to work around a race condition in set_cpus_allowed(). Without this hack, the kernel would almost always die as soon as it tried to migrate ksoftirqd_CPU1 from CPU 0 to CPU 1. With the patch, it boots up to the point where the serial line driver gets initialized, which is progress, I suppose.

The fundamental problem is that current set_cpus_allowed() lets the same task run on two CPUs for a brief period of time. This violates scheduling assumptions made by the kernel and hence results in race conditions.

	--david
#19 lore raw
In reply to Nick Pollitt
Quoted 8 lines · Erich Focht

Hmm, doesn't work, yet with 2.4.17 :-(

There must be some path where a rq->lock remains set, with some sort of print-eip-like tool I see lockups with

load_balance  vs.   __wake_up
__wake_up     vs.   sched_tick

etc...

are you sure interrupts are properly disabled in all cases where the runqueue is touched? Eg. sched_tick() relies on having IRQs disabled.

Ingo

#20 lore raw
In reply to Nick Pollitt
Quoted 9 lines · Ingo Molnar
Quoted 6 lines

There must be some path where a rq->lock remains set, with some sort of print-eip-like tool I see lockups with

load_balance  vs.   __wake_up
__wake_up     vs.   sched_tick

etc...

are you sure interrupts are properly disabled in all cases where the runqueue is touched? Eg. sched_tick() relies on having IRQs disabled.

Good question.

Actually I thought that local_irq_disable() really disables interrupts on a CPU but the debugging output of a crashing run with the new scheduler makes me believe that timer interrupts are still being delivered to the CPU. Have a look yourself: I printed function addresses to video memory and the history is the following (time arrow points upwards):

CPU # 0:
-------- locks
function: rq0 rq1 psr.i

debug_spin_lock 1 0 0
sched_tick 1 0 0
update_one_process 1 0 0
update_process_times 1 0 0
smp_do_timer 1 0 0
do_profile 1 0 0
timer_interrupt 1 0 0
handle_IRQ_event 1 0 0
lsapic_noop 1 0 0
do_IRQ 1 0 0
ia64_handle_irq 1 0 0
debug_spin_lock 0 0 0 <- locked rq0 lock, disabled irqs
spin_unlock 0 1 1 <- release_kernel_lock
schedule 0 1 1
spin_unlock 0 0 0
debug_spin_lock 0 0 0
wait_for_completion 0 0 1
spin_unlock 1 0 0
debug_spin_lock 0 0 0
wake_up_forked_process 0 1 1

CPU # 1:
--------
debug_spin_lock 1 0 0 <- tries to lock rq0 lock
spin_unlock 0 1 0 <- unlocked rq1 lock
load_balance 0 1 0
debug_spin_lock 0 0 0 <- lock rq1 lock, disable irqs
schedule 0 0 1

ia64_handle_irq() is called on CPU#0 while psr.i=0 which means: interrupts are disabled. Looking into the IA64 manuals I find that the text about psr.i emntions only disabling external interrupts, not the timer interrupt or internal interrupts coming from the local APIC (i.e. IPIs could also appear?).

Does anybody know whether psr.i disables all interrupts or not? I tried setting the mmi bit on cr.tpr (mask maskable interrupts) in local_irq_disable() and local_irq_restore(), but I still see this kind of lockups.

A quick fix for the scheduler is to return from the timer interrupt when the local runqueue is locked (same probably for IPIs) but ... isn't there a method to disable ALL interrupts?

Thanks,

Erich

#21 lore raw
In reply to Nick Pollitt
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Erich Focht

Erich> interrupts are disabled. Looking into the IA64 manuals Erich> I find that the text about psr.i emntions only disabling Erich> external interrupts, not the timer interrupt or internal Erich> interrupts coming from the local APIC (i.e. IPIs could also Erich> appear?).

Erich> Does anybody know whether psr.i disables all interrupts or Erich> not? I tried setting the mmi bit on cr.tpr (mask maskable Erich> interrupts) in local_irq_disable() and local_irq_restore(), Erich> but I still see this kind of lockups.

Erich> A quick fix for the scheduler is to return from the timer Erich> interrupt when the local runqueue is locked (same probably Erich> for IPIs) but ... isn't there a method to disable ALL Erich> interrupts?

psr.i *does* disable all interrupts, including NMI. Device interrupts are generally referred to as "external interrupts" in the ia64 manuals. If you read the manual, you'll find there is no ambiguity about this at all. For example, see Table 5-8: External Interrupt Control Registers; it lists ITV...

	--david
#22 lore raw
In reply to Nick Pollitt

Hi David,

Quoted 5 lines

psr.i *does* disable all interrupts, including NMI. Device interrupts are generally referred to as "external interrupts" in the ia64 manuals. If you read the manual, you'll find there is no ambiguity about this at all. For example, see Table 5-8: External Interrupt Control Registers; it lists ITV...

ok, I see what you mean and this is the behavior I expected from psr.i. But in the paragraph at the beginning of 5.8 describing which sources of interrupts we have I read:
- external (I/O) devices...
- locally connected devices (...can be programmed to generate external interrupts)
- internal processor interrupts (timer, performance monitoring, corrected machine checks)
- other processors.
So if the interrupts called explicitely "internal" have "External Interrupt Control Registers" (as you pointed out in your email), why do we need to call the interrupts "external" at all? Anyhow, as I'm not a native english speaker, I might have misunderstood something.

My main problem still remains: how can it be that on CPU#0 the timer_interrupt() routine is called while in schedule() and while interrupts are disabled (psr.i is in the last column)? I paste the trace again, one can follow the irq disabling and the runqueue locking very nicely. I've seen this kind of lockup more than once and the mcount compiler trick is very acurate in catching/showing each function the kernel goes through.

So: if psr.i disables all interrupts, how can the timer interrupt appear while we're in schedule()?

Thanks,
Erich

CPU # 0:
-------- locks
function: rq0 rq1 psr.i

debug_spin_lock         1       0       0
sched_tick              1       0       0
update_one_process      1       0       0
update_process_times    1       0       0
smp_do_timer            1       0       0
do_profile              1       0       0
timer_interrupt         1       0       0
handle_IRQ_event        1       0       0
lsapic_noop             1       0       0
do_IRQ                  1       0       0
ia64_handle_irq         1       0       0
debug_spin_lock         0       0       0    <- locked rq0 lock, disabled irqs
spin_unlock             0       1       1    <- release_kernel_lock
schedule                0       1       1
spin_unlock             0       0       0
debug_spin_lock         0       0       0
wait_for_completion     0       0       1
spin_unlock             1       0       0
debug_spin_lock         0       0       0
wake_up_forked_process  0       1       1

CPU # 1:
--------

debug_spin_lock         1       0       0    <- tries to lock rq0 lock
spin_unlock             0       1       0    <- unlocked rq1 lock
load_balance            0       1       0
debug_spin_lock         0       0       0    <- lock rq1 lock, disable irqs
schedule                0       0       1
#23 lore raw
In reply to Nick Pollitt

Please ignore my previous email. The interrupt can of course come from within the context_switch() part in schedule(), where psr.i is set.

Unfortunately the context switch in Ingo's scheduler happens with the runqueue lock held, which can lead to a deadlock eg. if the timer interrupt is called inside and sched_tick spinlocks on the runqueue lock held by schedule(). On IA64 (HZ24) this probably happens much more frequently than on IA32 (HZ0).

Regards,
Erich

Quoted 7 lines · David Mosberger

psr.i *does* disable all interrupts, including NMI. Device interrupts are generally referred to as "external interrupts" in the ia64 manuals. If you read the manual, you'll find there is no ambiguity about this at all. For example, see Table 5-8: External Interrupt Control Registers; it lists ITV...

	--david
#24 lore raw
In reply to Nick Pollitt

Hi Ingo,

what's the problem with the following code?

switch_tasks:

	prev->need_resched = 0;

	if (likely(prev != next)) {
		rq->nr_switches++;
		rq->curr = next;
		spin_unlock_irq(&rq->lock);          // <-
		context_switch(prev, next, 0);
		/*
		 * The runqueue pointer might be from another CPU
		 * if the new task was last running on a different
		 * CPU - thus re-load it.
		 */
		barrier();
		rq = this_rq();
		spin_lock_irq(&rq->lock);           // <-
	}

	spin_unlock_irq(&rq->lock);

Thanks,
Erich

Quoted 13 lines · Ingo Molnar
Quoted 5 lines · Erich Focht

Unfortunately the context switch in Ingo's scheduler happens with the runqueue lock held, which can lead to a deadlock eg. if the timer interrupt is called inside and sched_tick spinlocks on the runqueue lock held by schedule(). On IA64 (HZ24) this probably happens much more frequently than on IA32 (HZ0).

we call context_switch() with irqs disabled. The ia64 version of switch_to() should not re-enable IRQs or it will deadlock.

Ingo

#25 lore raw
In reply to Nick Pollitt
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Ingo Molnar
Quoted 5 lines · Erich Focht
Quoted 5 lines

Unfortunately the context switch in Ingo's scheduler happens with the runqueue lock held, which can lead to a deadlock eg. if the timer interrupt is called inside and sched_tick spinlocks on the runqueue lock held by schedule(). On IA64 (HZ24) this probably happens much more frequently than on IA32 (HZ0).

Ingo> we call context_switch() with irqs disabled. The ia64 version Ingo> of switch_to() should not re-enable IRQs or it will deadlock.

The existing switch_to() enables interrupts if the new task's stack is on a different (kernel-) page. If the new scheduler guarantees to call switch_to() with irqs disabled, we can simply drop the relevant code.

	--david
#26 lore raw
In reply to Nick Pollitt
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Ingo Molnar

Ingo> On Mon, 21 Jan 2002, David Mosberger wrote:

Ingo> we call context_switch() with irqs disabled. The ia64 version Ingo> of switch_to() should not re-enable IRQs or it will deadlock.

Quoted 2 lines
Quoted 2 lines

The existing switch_to() enables interrupts if the new task's
stack is on a different (kernel-) page.

Ingo> oh, i see. Why were irqs enabled explicitly? The old scheduler Ingo> called switch_to() with irqs enabled, all the time.

Eh, that's not true. The old scheduler did spin_unlock_irq() before calling switch_to(). If your scheduler requires irq's to be disabled during context switch, it's going to have bigger interrupt response latency. That's a disadvantage.

	--david
#27 lore raw
In reply to Nick Pollitt
Quoted 5 lines · Erich Focht

Unfortunately the context switch in Ingo's scheduler happens with the runqueue lock held, which can lead to a deadlock eg. if the timer interrupt is called inside and sched_tick spinlocks on the runqueue lock held by schedule(). On IA64 (HZ24) this probably happens much more frequently than on IA32 (HZ0).

we call context_switch() with irqs disabled. The ia64 version of switch_to() should not re-enable IRQs or it will deadlock.

Ingo

#28 lore raw
In reply to Nick Pollitt
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Ingo Molnar

Ingo> Besides causing the current bug, it was superfluous in the old Ingo> scheduler as well, so i'm only wondering aloud - perhaps there Ingo> were more subtle reasons as well?

No, it wasn't superfluous. It had to re-establish the original state after disabling interrupts to switch the TLB pinning.

	--david
#29 lore raw
In reply to Nick Pollitt
Quoted 10 lines · Erich Focht

what's the problem with the following code?

switch_tasks:

	prev->need_resched = 0;

	if (likely(prev != next)) {
		rq->nr_switches++;
		rq->curr = next;
		spin_unlock_irq(&rq->lock);          // <-
		context_switch(prev, next, 0);

the runqueue must not be unlocked before the current task is completely inactive - otherwise another CPU could grab (or even free) this task.

Ingo

#30 lore raw
In reply to Nick Pollitt
Quoted 5 lines · David Mosberger

Ingo> we call context_switch() with irqs disabled. The ia64 version Ingo> of switch_to() should not re-enable IRQs or it will deadlock.

The existing switch_to() enables interrupts if the new task's stack is on a different (kernel-) page.

oh, i see. Why were irqs enabled explicitly? The old scheduler called switch_to() with irqs enabled, all the time.

Quoted 2 lines

[...] If the new scheduler guarantees to call switch_to() with irqs disabled, we can simply drop the relevant code.

yes. And this should fix the lockup as well.

Ingo

#31 lore raw
In reply to Nick Pollitt
Quoted 5 lines · David Mosberger

Ingo> oh, i see. Why were irqs enabled explicitly? The old scheduler Ingo> called switch_to() with irqs enabled, all the time.

Eh, that's not true. The old scheduler did spin_unlock_irq() before calling switch_to(). [...]

hey, thats the same thing i said. "The old scheduler called switch_to() with irqs enabled". Ie. with irqs not turned off. I should know, i implemented that particular aspect of the old scheduler.

Quoted 3 lines

[...] If your scheduler requires irq's to be disabled during context switch, it's going to have bigger interrupt response latency. That's a disadvantage.

we disable interrupts for a microsecond or two pretty often. (i'm not sure about ia64's context switch speed, but it should be well below 10 usecs, right?)

Disabling interrupts for possibly hundreds of microseconds like the old scheduler did, with the runqueue lock held, that was a disadvantage, i agree.

Ingo

#32 lore raw
In reply to Nick Pollitt
Quoted 4 lines · David Mosberger

Ingo> oh, i see. Why were irqs enabled explicitly? The old scheduler Ingo> called switch_to() with irqs enabled, all the time.

Eh, that's not true. [...]

my 'Why were irqs enabled explicitly' question referred to the ia64 switch_to() code, which, if i understand this thread correctly, enables interrupts internally.

Besides causing the current bug, it was superfluous in the old scheduler as well, so i'm only wondering aloud - perhaps there were more subtle reasons as well?

Ingo

#33 lore raw
In reply to Nick Pollitt
Quoted 6 lines · David Mosberger

Ingo> Besides causing the current bug, it was superfluous in the old Ingo> scheduler as well, so i'm only wondering aloud - perhaps there Ingo> were more subtle reasons as well?

No, it wasn't superfluous. It had to re-establish the original state after disabling interrupts to switch the TLB pinning.

since it went in pair with an irq-disable, it was indeed necessery.

i think i understand it now.

the end result: in the new scheduler it's guaranteed that switch_to() is called with local interrupts disabled, and it's not allowed to reenable them during switch_to().

Ingo