patch-2.1.127 linux/arch/sparc64/kernel/process.c

Next file: linux/arch/sparc64/kernel/psycho.c
Previous file: linux/arch/sparc64/kernel/irq.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.126/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.75 1998/09/23 02:05:15 davem Exp $
+/*  $Id: process.c,v 1.82 1998/10/19 21:52:23 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -71,13 +71,16 @@
 {
 	current->priority = 0;
 	while(1) {
+		struct task_struct *p;
+
 		check_pgt_cache();
 		run_task_queue(&tq_scheduler);
-		barrier();
 		current->counter = 0;
-		if(current->need_resched)
+		if (current->need_resched != 0 ||
+		    ((p = init_task.next_run) != NULL &&
+		     (p->processor == smp_processor_id() ||
+		      (p->tss.flags & SPARC_FLAG_NEWCHILD) != 0)))
 			schedule();
-		barrier();
 	}
 }
 
@@ -386,12 +389,32 @@
 		else
 			current->tss.utraps[0]--;
 	}
+
+	/* Turn off performance counters if on. */
+	if (current->tss.flags & SPARC_FLAG_PERFCTR) {
+		current->tss.user_cntd0 =
+			current->tss.user_cntd1 = NULL;
+		current->tss.pcr_reg = 0;
+		current->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+		write_pcr(0);
+	}
 }
 
 void flush_thread(void)
 {
+	if (!(current->tss.flags & SPARC_FLAG_KTHREAD))
+		flush_user_windows();
 	current->tss.w_saved = 0;
 
+	/* Turn off performance counters if on. */
+	if (current->tss.flags & SPARC_FLAG_PERFCTR) {
+		current->tss.user_cntd0 =
+			current->tss.user_cntd1 = NULL;
+		current->tss.pcr_reg = 0;
+		current->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+		write_pcr(0);
+	}
+
 	/* No new signal delivery by default. */
 	current->tss.new_signal = 0;
 	current->tss.fpsaved[0] = 0;
@@ -399,18 +422,14 @@
 	/* Now, this task is no longer a kernel thread. */
 	current->tss.current_ds = USER_DS;
 	if(current->tss.flags & SPARC_FLAG_KTHREAD) {
-		extern spinlock_t scheduler_lock;
-
 		current->tss.flags &= ~SPARC_FLAG_KTHREAD;
 
 		/* exec_mmap() set context to NO_CONTEXT, here is
 		 * where we grab a new one.
 		 */
-		spin_lock(&scheduler_lock);
 		current->mm->cpu_vm_mask = 0;
 		activate_context(current);
 		current->mm->cpu_vm_mask = (1UL<<smp_processor_id());
-		spin_unlock(&scheduler_lock);
 	}
 	if (current->tss.flags & SPARC_FLAG_32BIT)
 		__asm__ __volatile__("stxa %%g0, [%0] %1"
@@ -524,7 +543,6 @@
 	current->tss.w_saved = 0;
 	return;
 barf:
-	lock_kernel();
 	do_exit(SIGILL);
 }
 
@@ -552,7 +570,19 @@
 	p->tss.kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
 	p->tss.cwp = (regs->tstate + 1) & TSTATE_CWP;
 	p->tss.fpsaved[0] = 0;
+	p->mm->segments = (void *) 0;
 	if(regs->tstate & TSTATE_PRIV) {
+		/* Special case, if we are spawning a kernel thread from
+		 * a userspace task (via KMOD, NFS, or similar) we must
+		 * disable performance counters in the child because the
+		 * address space and protection realm are changing.
+		 */
+		if (current->tss.flags & SPARC_FLAG_PERFCTR) {
+			p->tss.user_cntd0 =
+				p->tss.user_cntd1 = NULL;
+			p->tss.pcr_reg = 0;
+			p->tss.flags &= ~(SPARC_FLAG_PERFCTR);
+		}
 		p->tss.kregs->u_regs[UREG_FP] = p->tss.ksp;
 		p->tss.flags |= (SPARC_FLAG_KTHREAD | SPARC_FLAG_NEWCHILD);
 		p->tss.current_ds = KERNEL_DS;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov