From owner-p4-projects@FreeBSD.ORG Tue Jun 20 11:35:26 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7B2CD16A47E; Tue, 20 Jun 2006 11:35:26 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3E19D16A47C for ; Tue, 20 Jun 2006 11:35:26 +0000 (UTC) (envelope-from lawrance@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id F14E143D48 for ; Tue, 20 Jun 2006 11:35:25 +0000 (GMT) (envelope-from lawrance@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k5KBZPtZ003863 for ; Tue, 20 Jun 2006 11:35:25 GMT (envelope-from lawrance@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k5KBZPgq003860 for perforce@freebsd.org; Tue, 20 Jun 2006 11:35:25 GMT (envelope-from lawrance@freebsd.org) Date: Tue, 20 Jun 2006 11:35:25 GMT Message-Id: <200606201135.k5KBZPgq003860@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to lawrance@freebsd.org using -f From: Sam Lawrance To: Perforce Change Reviews Cc: Subject: PERFORCE change 99668 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Jun 2006 11:35:26 -0000 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.