Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 Jun 2006 11:35:25 GMT
From:      Sam Lawrance <lawrance@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 99668 for review
Message-ID:  <200606201135.k5KBZPgq003860@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=99668

Change 99668 by lawrance@dirk on 2006/06/20 11:35:12

	Implement DTrace raise() and stop() actions (the latter is
	assumed to be bogus at the moment).
	
	If there's a better lock-free way to get an AST from probe
	context, please let me know.
	
	- Move td_dtrace_sig and td_dtrace_stop earlier in struct thread,
	  so they are zeroed out on initialisation.  Other DTrace fields may
	  benefit from this, I only moved the ones that I needed.
	- Solaris uses t_astflag and t_sig_check to invoke this behaviour
	  without using locks in probe context.  The equivalents on FreeBSD
	  are td_flags fields TDF_ASTPENDING and TDF_NEEDSIGCHK.  FreeBSD's
	  td_flags is protected by sched_lock.  To work around this I added
	  TDP_ASTPENDING and TDP_NEEDSIGCHK fields to td_pflags.  They are
	  just like the td_flags equivalents, except that td_pflags is
	  private to curthread, so no locking is required in probe context
	  to modify them.
	- I added additional behaviour to i386/i386/exception.s to check
	  for TDP_ASTPENDING.
	- ast() checks and clears TDP_NEEDSIGCHK and TDP_ASTPENDING.
	  If TDP_NEEDSIGCHK is set, TDF_NEEDSIGCHK is set in flags.

Affected files ...

.. //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace_action.c#6 edit
.. //depot/projects/dtrace/src/sys/i386/i386/exception.s#5 edit
.. //depot/projects/dtrace/src/sys/i386/i386/genassym.c#2 edit
.. //depot/projects/dtrace/src/sys/kern/kern_sig.c#4 edit
.. //depot/projects/dtrace/src/sys/kern/subr_trap.c#2 edit
.. //depot/projects/dtrace/src/sys/sys/proc.h#8 edit

Differences ...

==== //depot/projects/dtrace/src/sys/cddl/dev/dtrace/dtrace_action.c#6 (text+ko) ====

@@ -103,17 +103,14 @@
 		return;
 	}
 
-#ifdef DOODAD
 	/*
 	 * raise() has a queue depth of 1 -- we ignore all subsequent
 	 * invocations of the raise() action.
 	 */
-	if (curthread->t_dtrace_sig == 0)
-		curthread->t_dtrace_sig = (uint8_t)sig;
+	if (curthread->td_dtrace_sig == 0)
+		curthread->td_dtrace_sig = (uint8_t)sig;
 
-	curthread->t_sig_check = 1;
-	aston(curthread);
-#endif
+	curthread->td_pflags |= TDP_NEEDSIGCHK | TDP_ASTPENDING;
 }
 
 static void
@@ -122,13 +119,14 @@
 	if (dtrace_destructive_disallow)
 		return;
 
-#ifdef DOODAD
-	if (!curthread->t_dtrace_stop) {
-		curthread->t_dtrace_stop = 1;
-		curthread->t_sig_check = 1;
-		aston(curthread);
+	if (!curthread->td_dtrace_stop) {
+		/* XXX stop it with a SIGSTOP for now.  This is not
+		 * how it is done on opensolaris.
+		 */
+		curthread->td_dtrace_stop = 1;
+		curthread->td_dtrace_sig = SIGSTOP;
+		curthread->td_pflags |= TDP_NEEDSIGCHK | TDP_ASTPENDING;
 	}
-#endif
 }
 
 static void

==== //depot/projects/dtrace/src/sys/i386/i386/exception.s#5 (text+ko) ====

@@ -446,7 +446,10 @@
 	cli
 	movl	PCPU(CURTHREAD),%eax
 	testl	$TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%eax)
+	jne	doreti_doast
+	testl	$TDP_ASTPENDING, TD_PFLAGS(%eax)
 	je	doreti_exit
+doreti_doast:
 	sti
 	pushl	%esp			/* pass a pointer to the trapframe */
 	call	ast

==== //depot/projects/dtrace/src/sys/i386/i386/genassym.c#2 (text+ko) ====

@@ -82,6 +82,7 @@
 
 ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
 ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
+ASSYM(TD_PFLAGS, offsetof(struct thread, td_pflags));
 ASSYM(TD_PROC, offsetof(struct thread, td_proc));
 ASSYM(TD_MD, offsetof(struct thread, td_md));
 
@@ -90,6 +91,7 @@
 
 ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
 ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
+ASSYM(TDP_ASTPENDING, TDP_ASTPENDING);
 
 ASSYM(V_TRAP, offsetof(struct vmmeter, v_trap));
 ASSYM(V_SYSCALL, offsetof(struct vmmeter, v_syscall));

==== //depot/projects/dtrace/src/sys/kern/kern_sig.c#4 (text+ko) ====


==== //depot/projects/dtrace/src/sys/kern/subr_trap.c#2 (text+ko) ====

@@ -194,6 +194,16 @@
 	mtx_unlock_spin(&sched_lock);
 
 	/*
+	 * Clear AST from pflags; if signal delivery is
+	 * required, poke flags to do the job.
+	 */
+	td->td_pflags &= ~(TDP_ASTPENDING);
+	if (td->td_pflags & TDP_NEEDSIGCHK) {
+		td->td_pflags &= ~TDP_NEEDSIGCHK;
+		flags |= TDF_NEEDSIGCHK;
+	}
+
+	/*
 	 * XXXKSE While the fact that we owe a user profiling
 	 * tick is stored per KSE in this code, the statistics
 	 * themselves are still stored per process.
@@ -266,6 +276,11 @@
 	if (flags & TDF_NEEDSIGCHK) {
 		PROC_LOCK(p);
 		mtx_lock(&p->p_sigacts->ps_mtx);
+		/* Signals from DTrace jump the queue. */
+		if (td->td_dtrace_sig != 0) {
+			postsig(td->td_dtrace_sig);
+			td->td_dtrace_sig = 0;
+		}
 		while ((sig = cursig(td)) != 0)
 			postsig(sig);
 		mtx_unlock(&p->p_sigacts->ps_mtx);

==== //depot/projects/dtrace/src/sys/sys/proc.h#8 (text+ko) ====

@@ -298,6 +298,9 @@
 	u_long		td_profil_addr;	/* (k) Temporary addr until AST. */
 	u_int		td_profil_ticks; /* (k) Temporary ticks until AST. */
 	char		td_name[MAXCOMLEN + 1];	/* (*) Thread name. */
+/* DTrace fields to be zeroed out */
+	u_int8_t	td_dtrace_stop;	/* Indicates a DTrace-desired stop */
+	u_int8_t	td_dtrace_sig;	/* Signal sent via DTrace's raise() */
 #define	td_endzero td_base_pri
 
 /* Copied during fork1() or thread_sched_upcall(). */
@@ -334,14 +337,9 @@
 
 /* Start of DTrace-specific fields. */
 	u_int		td_predcache;	/* DTrace predicate cache */
-	u_int64_t	td_dtrace_vtime;
-					/* DTrace virtual time */
-	u_int64_t	td_dtrace_start;
-					/* DTrace slice start time */
+	u_int64_t	td_dtrace_vtime; /* DTrace virtual time */
+	u_int64_t	td_dtrace_start; /* DTrace slice start time */
 
-	u_int8_t	td_dtrace_stop;	/* Indicates a DTrace-desired stop */
-	u_int8_t	td_dtrace_sig;	/* Signal sent via DTrace's raise() */
-
 	union __tdu {
 		struct __tds {
 			u_int8_t	_td_dtrace_on;
@@ -427,6 +425,8 @@
 #define	TDP_GEOM	0x00010000 /* Settle GEOM before finishing syscall */
 #define	TDP_SOFTDEP	0x00020000 /* Stuck processing softdep worklist */
 #define	TDP_NORUNNINGBUF 0x00040000 /* Ignore runningbufspace check */
+#define	TDP_ASTPENDING	0x00080000 /* Thread has some asynchronous events. */
+#define	TDP_NEEDSIGCHK	0x00100000 /* Thread may need signal delivery. */
 
 /*
  * Reasons that the current thread can not be run yet.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606201135.k5KBZPgq003860>