PERFORCE change 99668 for review
Sam Lawrance
lawrance at FreeBSD.org
Tue Jun 20 11:35:26 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=99668
Change 99668 by lawrance at 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.
More information about the p4-projects
mailing list