diff -u -p -L linux-2.2.16/arch/i386/kernel/entry.S.orig linux-2.2.16/arch/i386/kernel/entry.S
--- linux-2.2.16/arch/i386/kernel/entry.S
+++ linux-2.2.16/arch/i386/kernel/entry.S	Mon Aug 28 07:36:51 2000
@@ -564,6 +564,16 @@ ENTRY(sys_call_table)
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams1 */
 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams2 */
 	.long SYMBOL_NAME(sys_vfork)            /* 190 */
+	.long SYMBOL_NAME(sys_ni_syscall)		/* ugetrlimit */
+	.long SYMBOL_NAME(sys_ni_syscall)		/* mmap2 */
+	.long SYMBOL_NAME(sys_ni_syscall)		/* truncate64 */
+	.long SYMBOL_NAME(sys_ni_syscall)		/* ftruncate64 */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* 195 */	/* stat64 */
+	.long SYMBOL_NAME(sys_ni_syscall)		/* lstat64 */
+	.long SYMBOL_NAME(sys_ni_syscall)		/* fstat64 */
+	.long SYMBOL_NAME(sys_smp_processor)
+	.long SYMBOL_NAME(sys_smp_lockto)
+	.long SYMBOL_NAME(sys_smp_num_cpus)	/* 200 */
 
 	/*
 	 * NOTE!! This doesn't have to be exact - we just have
@@ -571,6 +581,6 @@ ENTRY(sys_call_table)
 	 * entries. Don't panic if you notice that this hasn't
 	 * been shrunk every time we add a new system call.
 	 */
-	.rept NR_syscalls-190
+	.rept NR_syscalls-200
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -u -p -L linux-2.2.16/include/asm-i386/unistd.h.orig linux-2.2.16/include/asm-i386/unistd.h
--- linux-2.2.16/include/asm-i386/unistd.h
+++ linux-2.2.16/include/asm-i386/unistd.h	Mon Aug 28 07:32:36 2000
@@ -202,6 +202,9 @@
 #define __NR_stat64		195
 #define __NR_lstat64		196
 #define __NR_fstat64		197
+#define __NR_smp_processor	198
+#define __NR_smp_lockto		199
+#define __NR_smp_num_cpus	200
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff -u -p -L linux-2.2.16/include/linux/sched.h.orig linux-2.2.16/include/linux/sched.h
--- linux-2.2.16/include/linux/sched.h
+++ linux-2.2.16/include/linux/sched.h	Mon Aug 28 12:57:12 2000
@@ -248,6 +248,7 @@ struct task_struct {
 	int processor;
 	int last_processor;
 	int lock_depth;		/* Lock depth. We can context switch in and out of holding a syscall kernel lock... */	
+	int locked_processor;
 	struct task_struct *next_task, *prev_task;
 	struct task_struct *next_run,  *prev_run;
 
@@ -368,7 +369,7 @@ struct task_struct {
 #define INIT_TASK \
 /* state etc */	{ 0,0,0,KERNEL_DS,&default_exec_domain,0, \
 /* counter */	DEF_PRIORITY,DEF_PRIORITY,0, \
-/* SMP */	0,0,0,-1, \
+/* SMP */	0,0,0,-1,-1, \
 /* schedlink */	&init_task,&init_task, &init_task, &init_task, \
 /* binfmt */	NULL, \
 /* ec,brk... */	0,0,0,0,0,0, \
diff -u -p -L linux-2.2.16/kernel/fork.c.orig linux-2.2.16/kernel/fork.c
--- linux-2.2.16/kernel/fork.c
+++ linux-2.2.16/kernel/fork.c	Mon Aug 28 07:27:55 2000
@@ -656,6 +656,8 @@ int do_fork(unsigned long clone_flags, u
 		int i;
 		p->has_cpu = 0;
 		p->processor = current->processor;
+		/* New process will follow parent's locking */
+		p->locked_processor = current->locked_processor;
 		/* ?? should we just memset this ?? */
 		for(i = 0; i < smp_num_cpus; i++)
 			p->per_cpu_utime[i] = p->per_cpu_stime[i] = 0;
diff -u -p -L linux-2.2.16/kernel/sched.c.orig linux-2.2.16/kernel/sched.c
--- linux-2.2.16/kernel/sched.c
+++ linux-2.2.16/kernel/sched.c	Mon Aug 28 07:27:55 2000
@@ -15,6 +15,7 @@
  *				Copyright (C) 1998  Andrea Arcangeli
  *  1998-12-28  Implemented better SMP scheduling by Ingo Molnar
  *  1999-03-10	Improved NTP compatibility by Ulrich Windl
+ *  2000-02-01	SMP processor locking by Fred Barnes
  */
 
 /*
@@ -171,6 +172,13 @@ static inline int goodness (struct task_
 	/* (this is equivalent to penalizing other processors) */
 	if (p->processor == this_cpu)
 		weight += PROC_CHANGE_PENALTY;
+	/*
+	 *	If process locked to a processor, never select it
+	 */
+	if( (p->locked_processor > -1) && (p->locked_processor != this_cpu) ) {
+		weight = -1000;
+		goto out;
+	}
 #endif
 
 	/* .. and a slight advantage to the current MM */
@@ -280,7 +288,15 @@ static inline void reschedule_idle_slow(
 	 * shortcut if the woken up task's last CPU is
 	 * idle now.
 	 */
-	best_cpu = p->processor;
+
+	/*
+	 * if process is locked to a processor, preferred CPU is that one
+	 */
+	if (p->locked_processor > -1) {
+		best_cpu = p->locked_processor;
+	} else {
+		best_cpu = p->processor;
+	}
 	target_tsk = idle_task(best_cpu);
 	if (cpu_curr(best_cpu) == target_tsk)
 		goto send_now;
@@ -301,8 +317,16 @@ static inline void reschedule_idle_slow(
 	/*
 	 * found any suitable CPU?
 	 */
-	if (!target_tsk)
+	if (!target_tsk) {
 		goto out_no_target;
+	} else {
+		/*
+		 * avoid scheduling on another processor
+		 */
+		if ((p->locked_processor > -1) && (p->locked_processor != target_tsk->processor)) {
+			goto out_no_target;
+		}
+	}
 		
 send_now:
 	target_cpu = target_tsk->processor;
@@ -2067,6 +2091,7 @@ void __init sched_init(void)
 	int nr = NR_TASKS;
 
 	init_task.processor=cpu;
+	init_task.locked_processor = -1;
 
 	/* Init task array free list and pidhash table. */
 	while(--nr > 0)
diff -u -p -L linux-2.2.16/kernel/sys.c.orig linux-2.2.16/kernel/sys.c
--- linux-2.2.16/kernel/sys.c
+++ linux-2.2.16/kernel/sys.c	Mon Aug 28 07:27:55 2000
@@ -1023,3 +1023,39 @@ asmlinkage int sys_prctl(int option, uns
 	return error;
 }
 
+asmlinkage int sys_smp_num_cpus (void)
+{
+	#ifdef __SMP__
+		return smp_num_cpus;
+	#else
+		return -ENOSYS;
+	#endif
+}
+
+asmlinkage int sys_smp_processor (void)
+{
+	#ifdef __SMP__
+		return smp_processor_id ();
+	#else
+		return -ENOSYS;
+	#endif
+}
+
+asmlinkage int sys_smp_lockto (int proc_id)
+{
+	#ifdef __SMP__
+		if ((proc_id != -1) && (proc_id >= smp_num_cpus)) {
+			return -EINVAL;
+		}
+		if (proc_id != current->locked_processor) {
+			current->locked_processor = proc_id;
+			schedule ();
+		}
+		return 0;
+	#else
+		return -ENOSYS;
+	#endif
+}
+
+
+

