DragonFly bugs List (threaded) for 2007-12
DragonFly BSD
DragonFly bugs List (threaded) for 2007-12
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Re: [issue871] gtk2 related: X mouse pointer jumps and sticks to top left corner


From: Matthew Dillon <dillon@xxxxxxxxxxxxxxxxxxxx>
Date: Thu, 6 Dec 2007 19:16:46 -0800 (PST)

    Ok, I would like people with this problem to test this patch.

    (1) BEFORE applying the patch get your X server setup so the mouse pointer
	bugs out.

    (2) Apply patch

    (3) Re-test

    This code isn't very efficient but, hey, its a signal handler so at
    the moment I don't care.

    p.s. for some reason the regression test failed to detect the FP
    trashing in my pre-patch tests.  I don't know why.

						-Matt

Index: platform/pc32/i386/machdep.c
===================================================================
RCS file: /cvs/src/sys/platform/pc32/i386/machdep.c,v
retrieving revision 1.128
diff -u -p -r1.128 machdep.c
--- platform/pc32/i386/machdep.c	7 Nov 2007 17:42:50 -0000	1.128
+++ platform/pc32/i386/machdep.c	7 Dec 2007 02:56:39 -0000
@@ -498,6 +498,11 @@ 		tf->tf_eflags &= ~(PSL_VM | PSL_NT | P
 	}
 
 	/*
+	 * Save the FPU state and reinit the FP unit
+	 */
+	npxpush(&sf.sf_uc.uc_mcontext);
+
+	/*
 	 * Copy the sigframe out to the user's stack.
 	 */
 	if (copyout(&sf, sfp, sizeof(struct sigframe)) != 0) {
@@ -679,6 +684,11 @@ 		bcopy(&ucp->uc_mcontext.mc_gs, regs, s
 	}
 
 	/*
+	 * Restore the FPU state from the frame
+	 */
+	npxpop(&ucp->uc_mcontext);
+
+	/*
 	 * Merge saved signal mailbox pending flag to maintain interlock
 	 * semantics against system calls.
 	 */
Index: platform/pc32/include/md_var.h
===================================================================
RCS file: /cvs/src/sys/platform/pc32/include/md_var.h,v
retrieving revision 1.25
diff -u -p -r1.25 md_var.h
--- platform/pc32/include/md_var.h	9 Jan 2007 23:34:03 -0000	1.25
+++ platform/pc32/include/md_var.h	7 Dec 2007 01:15:37 -0000
@@ -69,6 +69,7 @@ 
 struct  dbreg;
 struct  mdglobaldata;
 struct  thread;
+struct	__mcontext;
 
 void	busdma_swi (void);
 void	cpu_gdinit (struct mdglobaldata *gd, int cpu);
@@ -113,5 +114,7 @@ 		    int selec);
 void	userconfig (void);
 int     user_dbreg_trap (void);
 int     npxdna(void);
+void	npxpush(struct __mcontext *mctx);
+void	npxpop(struct __mcontext *mctx);
 
 #endif /* !_MACHINE_MD_VAR_H_ */
Index: platform/pc32/isa/npx.c
===================================================================
RCS file: /cvs/src/sys/platform/pc32/isa/npx.c,v
retrieving revision 1.42
diff -u -p -r1.42 npx.c
--- platform/pc32/isa/npx.c	22 Feb 2007 15:50:49 -0000	1.42
+++ platform/pc32/isa/npx.c	7 Dec 2007 03:12:46 -0000
@@ -513,7 +513,7 @@  */
 void
 npxinit(u_short control)
 {
-	static union savefpu dummy;
+	static union savefpu dummy __aligned(16);
 
 	if (!npx_exists)
 		return;
@@ -861,6 +861,17 @@ 		kprintf("npxdna: npxthread = %p, curth
 		       mdcpu->gd_npxthread, curthread);
 		panic("npxdna");
 	}
+
+	/*
+	 * Setup the initial saved state if the thread has never before
+	 * used the FP unit.  This also occurs when a thread pushes a
+	 * signal handler and uses FP in the handler.
+	 */
+	if ((curthread->td_flags & TDF_USINGFP) == 0) {
+		curthread->td_flags |= TDF_USINGFP;
+		npxinit(__INITIAL_NPXCW__);
+	}
+
 	/*
 	 * The setting of gd_npxthread and the call to fpurstor() must not
 	 * be preempted by an interrupt thread or we will take an npxdna
@@ -975,6 +986,78 @@ #endif
 		fnsave(addr);
 }
 
+/*
+ * Save the FP state to the mcontext structure.
+ *
+ * WARNING: If you want to try to npxsave() directly to mctx->mc_fpregs,
+ * then it MUST be 16-byte aligned.  Currently this is not guarenteed.
+ */
+void
+npxpush(mcontext_t *mctx)
+{
+	thread_t td = curthread;
+
+	if (td->td_flags & TDF_USINGFP) {
+		if (mdcpu->gd_npxthread == td) {
+			/*
+			 * XXX Note: This is a bit inefficient if the signal
+			 * handler uses floating point, extra faults will
+			 * occur.
+			 */
+			mctx->mc_ownedfp = _MC_FPOWNED_FPU;
+			npxsave(td->td_savefpu);
+		} else {
+			mctx->mc_ownedfp = _MC_FPOWNED_PCB;
+		}
+		bcopy(td->td_savefpu, mctx->mc_fpregs, sizeof(mctx->mc_fpregs));
+		td->td_flags &= ~TDF_USINGFP;
+	} else {
+		mctx->mc_ownedfp = _MC_FPOWNED_NONE;
+	}
+}
+
+/*
+ * Restore the FP state from the mcontext structure.
+ */
+void
+npxpop(mcontext_t *mctx)
+{
+	thread_t td = curthread;
+
+	switch(mctx->mc_ownedfp) {
+	case _MC_FPOWNED_NONE:
+		/*
+		 * If the signal handler used the FP unit but the interrupted
+		 * code did not, release the FP unit.  Clear TDF_USINGFP will
+		 * force the FP unit to reinit so the interrupted code sees
+		 * a clean slate.
+		 */
+		if (td->td_flags & TDF_USINGFP) {
+			if (td == mdcpu->gd_npxthread)
+				npxsave(td->td_savefpu);
+			td->td_flags &= ~TDF_USINGFP;
+		}
+		break;
+	case _MC_FPOWNED_FPU:
+	case _MC_FPOWNED_PCB:
+		/*
+		 * Clear ownership of the FP unit and restore our saved state.
+		 *
+		 * NOTE: The signal handler may have set-up some FP state and
+		 * enabled the FP unit, so we have to restore no matter what.
+		 *
+		 * XXX: This is bit inefficient, if the code being returned
+		 * to is actively using the FP this results in multiple
+		 * kernel faults.
+		 */
+		if (td == mdcpu->gd_npxthread)
+			npxsave(td->td_savefpu);
+		bcopy(mctx->mc_fpregs, td->td_savefpu, sizeof(*td->td_savefpu));
+		td->td_flags |= TDF_USINGFP;
+		break;
+	}
+}
+
 #ifndef CPU_DISABLE_SSE
 /*
  * On AuthenticAMD processors, the fxrstor instruction does not restore
Index: sys/thread.h
===================================================================
RCS file: /cvs/src/sys/sys/thread.h,v
retrieving revision 1.89
diff -u -p -r1.89 thread.h
--- sys/thread.h	18 Nov 2007 09:53:19 -0000	1.89
+++ sys/thread.h	7 Dec 2007 01:12:37 -0000
@@ -284,6 +284,7 @@ #define TDF_PANICWARN		0x00080000	/* pan
 #define TDF_BLOCKQ		0x00100000	/* on block queue */
 #define TDF_MPSAFE		0x00200000	/* (thread creation) */
 #define TDF_EXITING		0x00400000	/* thread exiting */
+#define TDF_USINGFP		0x00800000	/* thread using fp coproc */
 
 /*
  * Thread priorities.  Typically only one thread from any given



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]