Index: lib/libc/sys/Symbol.map =================================================================== --- lib/libc/sys/Symbol.map +++ lib/libc/sys/Symbol.map @@ -554,6 +554,7 @@ __sys_extattr_set_link; _extattrctl; __sys_extattrctl; + __sys_fast_sigblock; _fchdir; __sys_fchdir; _fchflags; Index: libexec/rtld-elf/rtld.h =================================================================== --- libexec/rtld-elf/rtld.h +++ libexec/rtld-elf/rtld.h @@ -360,6 +360,7 @@ extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; extern Elf_Sym sym_zero; /* For resolving undefined weak refs. */ extern bool ld_bind_not; +extern bool ld_fast_sigblock; void dump_relocations(Obj_Entry *); void dump_obj_relocations(Obj_Entry *); Index: libexec/rtld-elf/rtld.c =================================================================== --- libexec/rtld-elf/rtld.c +++ libexec/rtld-elf/rtld.c @@ -265,6 +265,7 @@ int tls_max_index = 1; /* Largest module index allocated */ bool ld_library_path_rpath = false; +bool ld_fast_sigblock = false; /* * Globals for path names, and such @@ -417,6 +418,10 @@ ((unsigned char *)(void *)__stack_chk_guard)[3] = 255; } } + if (aux_info[AT_BSDFLAGS] != NULL) { + if ((aux_info[AT_BSDFLAGS]->a_un.a_val & ELF_BSDF_FASTSIGBLK) != 0) + ld_fast_sigblock = true; + } trust = !issetugid(); Index: libexec/rtld-elf/rtld_lock.c =================================================================== --- libexec/rtld-elf/rtld_lock.c +++ libexec/rtld-elf/rtld_lock.c @@ -43,6 +43,7 @@ */ #include +#include #include #include #include @@ -65,6 +66,7 @@ static sigset_t fullsigmask, oldsigmask; static int thread_flag, wnested; +static uint32_t fsigblock; static void * def_lock_create(void) @@ -114,6 +116,16 @@ ; /* Spin */ } +static void +sig_fastunblock(void) +{ + uint32_t oldval; + + oldval = atomic_fetchadd_32(&fsigblock, -FAST_SIGBLOCK_INC); + if (oldval == (FAST_SIGBLOCK_PEND | FAST_SIGBLOCK_INC)) + __sys_fast_sigblock(FAST_SIGBLOCK_UNBLOCK, NULL); +} + static void def_wlock_acquire(void *lock) { @@ -121,14 +133,23 @@ sigset_t tmp_oldsigmask; l = (Lock *)lock; - for (;;) { - sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask); - if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG)) - break; - sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL); + if (ld_fast_sigblock) { + for (;;) { + atomic_add_32(&fsigblock, FAST_SIGBLOCK_INC); + if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG)) + break; + sig_fastunblock(); + } + } else { + for (;;) { + sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask); + if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG)) + break; + sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL); + } + if (atomic_fetchadd_int(&wnested, 1) == 0) + oldsigmask = tmp_oldsigmask; } - if (atomic_fetchadd_int(&wnested, 1) == 0) - oldsigmask = tmp_oldsigmask; } static void @@ -140,9 +161,10 @@ if ((l->lock & WAFLAG) == 0) atomic_add_rel_int(&l->lock, -RC_INCR); else { - assert(wnested > 0); atomic_add_rel_int(&l->lock, -WAFLAG); - if (atomic_fetchadd_int(&wnested, -1) == 1) + if (ld_fast_sigblock) + sig_fastunblock(); + else if (atomic_fetchadd_int(&wnested, -1) == 1) sigprocmask(SIG_SETMASK, &oldsigmask, NULL); } } @@ -295,19 +317,24 @@ memcpy(&lockinfo, &deflockinfo, sizeof(lockinfo)); _rtld_thread_init(NULL); - /* - * Construct a mask to block all signals except traps which might - * conceivably be generated within the dynamic linker itself. - */ - sigfillset(&fullsigmask); - sigdelset(&fullsigmask, SIGILL); - sigdelset(&fullsigmask, SIGTRAP); - sigdelset(&fullsigmask, SIGABRT); - sigdelset(&fullsigmask, SIGEMT); - sigdelset(&fullsigmask, SIGFPE); - sigdelset(&fullsigmask, SIGBUS); - sigdelset(&fullsigmask, SIGSEGV); - sigdelset(&fullsigmask, SIGSYS); + if (ld_fast_sigblock) + __sys_fast_sigblock(FAST_SIGBLOCK_SETPTR, &fsigblock); + else { + /* + * Construct a mask to block all signals except traps + * which might conceivably be generated within the + * dynamic linker itself. + */ + sigfillset(&fullsigmask); + sigdelset(&fullsigmask, SIGILL); + sigdelset(&fullsigmask, SIGTRAP); + sigdelset(&fullsigmask, SIGABRT); + sigdelset(&fullsigmask, SIGEMT); + sigdelset(&fullsigmask, SIGFPE); + sigdelset(&fullsigmask, SIGBUS); + sigdelset(&fullsigmask, SIGSEGV); + sigdelset(&fullsigmask, SIGSYS); + } } /* @@ -328,7 +355,10 @@ if (pli == NULL) pli = &deflockinfo; - + else if (ld_fast_sigblock) { + fsigblock = 0; + __sys_fast_sigblock(FAST_SIGBLOCK_UNSETPTR, NULL); + } for (i = 0; i < RTLD_LOCK_CNT; i++) if ((locks[i] = pli->lock_create()) == NULL) Index: sys/arm/include/elf.h =================================================================== --- sys/arm/include/elf.h +++ sys/arm/include/elf.h @@ -87,8 +87,9 @@ #define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */ #define AT_HWCAP 25 /* CPU feature flags. */ #define AT_HWCAP2 26 /* CPU feature flags 2. */ +#define AT_BSDFLAGS 27 /* ELF BSD Flags. */ -#define AT_COUNT 27 /* Count of defined aux entry types. */ +#define AT_COUNT 28 /* Count of defined aux entry types. */ #define R_ARM_COUNT 33 /* Count of defined relocation types. */ Index: sys/compat/freebsd32/syscalls.master =================================================================== --- sys/compat/freebsd32/syscalls.master +++ sys/compat/freebsd32/syscalls.master @@ -1119,3 +1119,4 @@ struct kevent32 *eventlist, \ int nevents, \ const struct timespec32 *timeout); } +561 AUE_NULL NOPROTO { int fast_sigblock(int cmd, uint32_t *ptr); } Index: sys/kern/imgact_elf.c =================================================================== --- sys/kern/imgact_elf.c +++ sys/kern/imgact_elf.c @@ -1135,6 +1135,7 @@ AUXARGS_ENTRY(pos, AT_HWCAP, *imgp->sysent->sv_hwcap); if (imgp->sysent->sv_hwcap2 != NULL) AUXARGS_ENTRY(pos, AT_HWCAP2, *imgp->sysent->sv_hwcap2); + AUXARGS_ENTRY(pos, AT_BSDFLAGS, ELF_BSDF_FASTSIGBLK); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); Index: sys/kern/kern_exec.c =================================================================== --- sys/kern/kern_exec.c +++ sys/kern/kern_exec.c @@ -1061,6 +1061,7 @@ int error; struct proc *p = imgp->proc; struct vmspace *vmspace = p->p_vmspace; + struct thread *td = curthread; vm_object_t obj; struct rlimit rlim_stack; vm_offset_t sv_minuser, stack_addr; @@ -1070,6 +1071,10 @@ imgp->vmspace_destroyed = 1; imgp->sysent = sv; + td->td_pflags &= ~TDP_FAST_SIGBLOCK; + td->td_sigblock_ptr = NULL; + td->td_sigblock_val = 0; + /* May be called with Giant held */ EVENTHANDLER_INVOKE(process_exec, p, imgp); Index: sys/kern/kern_fork.c =================================================================== --- sys/kern/kern_fork.c +++ sys/kern/kern_fork.c @@ -600,7 +600,8 @@ * been preserved. */ p2->p_flag |= p1->p_flag & P_SUGID; - td2->td_pflags |= (td->td_pflags & TDP_ALTSTACK) | TDP_FORKING; + td2->td_pflags |= (td->td_pflags & (TDP_ALTSTACK | + TDP_FAST_SIGBLOCK)) | TDP_FORKING; SESS_LOCK(p1->p_session); if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) p2->p_flag |= P_CONTROLT; Index: sys/kern/kern_proc.c =================================================================== --- sys/kern/kern_proc.c +++ sys/kern/kern_proc.c @@ -2881,6 +2881,77 @@ return (error); } +static int +sysctl_kern_proc_fastsigblk(SYSCTL_HANDLER_ARGS) +{ + int *name = (int *)arg1; + u_int namelen = arg2; + pid_t pid; + struct proc *p; + struct thread *td1; + uintptr_t addr; +#ifdef COMPAT_FREEBSD32 + uint32_t addr32; +#endif + int error; + + if (namelen != 1 || req->newptr != NULL) + return (EINVAL); + + pid = (pid_t)name[0]; + error = pget(pid, PGET_HOLD | PGET_NOTWEXIT | PGET_CANDEBUG, &p); + if (error != 0) + return (error); + + PROC_LOCK(p); +#ifdef COMPAT_FREEBSD32 + if (SV_CURPROC_FLAG(SV_ILP32)) { + if (!SV_PROC_FLAG(p, SV_ILP32)) { + error = EINVAL; + goto errlocked; + } + } +#endif + if (pid <= PID_MAX) { + td1 = FIRST_THREAD_IN_PROC(p); + } else { + FOREACH_THREAD_IN_PROC(p, td1) { + if (td1->td_tid == pid) + break; + } + } + if (td1 == NULL) { + error = ESRCH; + goto errlocked; + } + /* + * The access to the private thread flags. It is fine as far + * as no out-of-thin-air values are read from td_pflags, and + * usermode read of the td_sigblock_ptr is racy inherently, + * since target process might have already changed it + * meantime. + */ + if ((td1->td_pflags & TDP_FAST_SIGBLOCK) != 0) + addr = (uintptr_t)td1->td_sigblock_ptr; + else + error = ENOTTY; + +errlocked: + _PRELE(p); + PROC_UNLOCK(p); + if (error != 0) + return (error); + +#ifdef COMPAT_FREEBSD32 + if (SV_CURPROC_FLAG(SV_ILP32)) { + addr32 = addr; + error = SYSCTL_OUT(req, &addr32, sizeof(addr32)); + } else +#endif + error = SYSCTL_OUT(req, &addr, sizeof(addr)); + return (error); +} + SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD, 0, "Process table"); SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT| @@ -2994,6 +3065,10 @@ CTLFLAG_MPSAFE, sysctl_kern_proc_sigtramp, "Process signal trampoline location"); +static SYSCTL_NODE(_kern_proc, KERN_PROC_FASTSIGBLK, fastsigblk, CTLFLAG_RD | + CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_fastsigblk, + "Thread fast_sigblock address"); + int allproc_gen; /* Index: sys/kern/kern_sig.c =================================================================== --- sys/kern/kern_sig.c +++ sys/kern/kern_sig.c @@ -236,6 +236,7 @@ }; static void reschedule_signals(struct proc *p, sigset_t block, int flags); +static sigset_t fastblock_mask; static void sigqueue_start(void) @@ -246,6 +247,16 @@ p31b_setcfg(CTL_P1003_1B_REALTIME_SIGNALS, _POSIX_REALTIME_SIGNALS); p31b_setcfg(CTL_P1003_1B_RTSIG_MAX, SIGRTMAX - SIGRTMIN + 1); p31b_setcfg(CTL_P1003_1B_SIGQUEUE_MAX, max_pending_per_proc); + SIGFILLSET(fastblock_mask); + SIG_CANTMASK(fastblock_mask); + SIGDELSET(fastblock_mask, SIGILL); + SIGDELSET(fastblock_mask, SIGTRAP); + SIGDELSET(fastblock_mask, SIGABRT); + SIGDELSET(fastblock_mask, SIGEMT); + SIGDELSET(fastblock_mask, SIGFPE); + SIGDELSET(fastblock_mask, SIGBUS); + SIGDELSET(fastblock_mask, SIGSEGV); + SIGDELSET(fastblock_mask, SIGSYS); } ksiginfo_t * @@ -2805,6 +2816,24 @@ SIG_STOPSIGMASK(sigpending); if (SIGISEMPTY(sigpending)) /* no signal to send */ return (0); + + /* + * Do fast sigblock if requested by usermode. Since + * we do know that there was a signal pending at this + * point, set the FAST_SIGBLOCK_PEND as indicator for + * usermode to perform a dummy call to + * FAST_SIGBLOCK_UNBLOCK, which causes immediate + * delivery of postponed pending signal. + */ + if ((td->td_pflags & TDP_FAST_SIGBLOCK) != 0) { + if (td->td_sigblock_val != 0) + SIGSETNAND(sigpending, fastblock_mask); + if (SIGISEMPTY(sigpending)) { + td->td_pflags |= TDP_FAST_SIGPENDING; + return (0); + } + } + if ((p->p_flag & (P_TRACED | P_PPTRACE)) == P_TRACED && (p->p_flag2 & P2_PTRACE_FSTP) != 0 && SIGISMEMBER(sigpending, SIGSTOP)) { @@ -3737,3 +3766,92 @@ return (ps->ps_refcnt > 1); } + +int +sys_fast_sigblock(struct thread *td, struct fast_sigblock_args *uap) +{ + struct proc *p; + int error; + uint32_t oldval; + + error = 0; + switch (uap->cmd) { + case FAST_SIGBLOCK_SETPTR: + if ((td->td_pflags & TDP_FAST_SIGBLOCK) != 0) + error = EBUSY; + else if (((uintptr_t)(uap->ptr) & (sizeof(uint32_t) - 1)) != 0) + error = EINVAL; + else { + td->td_pflags |= TDP_FAST_SIGBLOCK; + td->td_sigblock_ptr = uap->ptr; + } + break; + + case FAST_SIGBLOCK_UNBLOCK: + if ((td->td_pflags & TDP_FAST_SIGBLOCK) != 0) { + oldval = casuword32(td->td_sigblock_ptr, + FAST_SIGBLOCK_PEND, 0); + if (oldval == (uint32_t)-1) + error = EFAULT; + else if (oldval != FAST_SIGBLOCK_PEND) + error = EBUSY; + else + td->td_sigblock_val = 0; + } else + error = EDOOFUS; + + /* + * Rely on normal ast mechanism to deliver pending + * signals to current thread. But notify others about + * fake unblock. + */ + p = td->td_proc; + if (error == 0 && p->p_numthreads != 1) { + PROC_LOCK(p); + reschedule_signals(p, td->td_sigmask, 0); + PROC_UNLOCK(p); + } + break; + + case FAST_SIGBLOCK_UNSETPTR: + if ((td->td_pflags & TDP_FAST_SIGBLOCK) != 0) { + error = copyin(td->td_sigblock_ptr, &oldval, + sizeof(uint32_t)); + if (error != 0) + break; + if (oldval != 0 && oldval != FAST_SIGBLOCK_PEND) + error = EBUSY; + else { + td->td_pflags &= ~TDP_FAST_SIGBLOCK; + td->td_sigblock_val = 0; + } + } else + error = EDOOFUS; + break; + } + return (error); +} + +void +fetch_fast_sigblock(struct thread *td) +{ + + if ((td->td_pflags & TDP_FAST_SIGBLOCK) == 0) + return; + td->td_sigblock_val = fuword32(td->td_sigblock_ptr); + if (td->td_sigblock_val == -1) + fetch_fast_sigblock_failed(td, 0); +} + +void +fetch_fast_sigblock_failed(struct thread *td, int write) +{ + ksiginfo_t ksi; + + td->td_sigblock_val = 0; + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGSEGV; + ksi.ksi_code = write ? SEGV_ACCERR : SEGV_MAPERR; + ksi.ksi_addr = td->td_sigblock_ptr; + trapsignal(td, &ksi); +} Index: sys/kern/subr_syscall.c =================================================================== --- sys/kern/subr_syscall.c +++ sys/kern/subr_syscall.c @@ -128,6 +128,12 @@ (*systrace_probe_func)(sa, SYSTRACE_ENTRY, 0); #endif + /* + * Fetch fast sigblock value at the time of syscall + * entry because sleepqueue primitives might call + * cursig(). + */ + fetch_fast_sigblock(td); AUDIT_SYSCALL_ENTER(sa->code, td); error = (sa->callp->sy_call)(td, sa->args); AUDIT_SYSCALL_EXIT(error, td); Index: sys/kern/subr_trap.c =================================================================== --- sys/kern/subr_trap.c +++ sys/kern/subr_trap.c @@ -207,8 +207,8 @@ { struct thread *td; struct proc *p; - int flags; - int sig; + uint32_t oldval; + int flags, sig; td = curthread; p = td->td_proc; @@ -307,6 +307,7 @@ */ if (flags & TDF_NEEDSIGCHK || p->p_pendingcnt > 0 || !SIGISEMPTY(p->p_siglist)) { + fetch_fast_sigblock(td); PROC_LOCK(p); mtx_lock(&p->p_sigacts->ps_mtx); while ((sig = cursig(td)) != 0) { @@ -316,6 +317,25 @@ mtx_unlock(&p->p_sigacts->ps_mtx); PROC_UNLOCK(p); } + + /* + * Handle deferred update of the fast sigblock value, after + * the postsig() loop was performed. + */ + if (td->td_pflags & TDP_FAST_SIGPENDING) { + td->td_pflags &= ~TDP_FAST_SIGPENDING; + oldval = fuword32(td->td_sigblock_ptr); + if (oldval == -1) { + fetch_fast_sigblock_failed(td, 0); + } else { + oldval |= FAST_SIGBLOCK_PEND; + if (suword32(td->td_sigblock_ptr, oldval) == -1) + fetch_fast_sigblock_failed(td, 1); + else + td->td_sigblock_val = oldval; + } + } + /* * We need to check to see if we have to exit or wait due to a * single threading requirement or some other STOP condition. Index: sys/kern/syscalls.master =================================================================== --- sys/kern/syscalls.master +++ sys/kern/syscalls.master @@ -1023,6 +1023,7 @@ struct kevent *changelist, int nchanges, \ struct kevent *eventlist, int nevents, \ const struct timespec *timeout); } +561 AUE_NULL STD { int fast_sigblock(int cmd, uint32_t *ptr); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master Index: sys/mips/include/elf.h =================================================================== --- sys/mips/include/elf.h +++ sys/mips/include/elf.h @@ -147,8 +147,9 @@ #define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */ #define AT_HWCAP 25 /* CPU feature flags. */ #define AT_HWCAP2 26 /* CPU feature flags 2. */ +#define AT_BSDFLAGS 27 /* ELF BSD Flags. */ -#define AT_COUNT 27 /* Count of defined aux entry types. */ +#define AT_COUNT 28 /* Count of defined aux entry types. */ #define ET_DYN_LOAD_ADDR 0x0120000 Index: sys/powerpc/include/elf.h =================================================================== --- sys/powerpc/include/elf.h +++ sys/powerpc/include/elf.h @@ -110,8 +110,9 @@ #define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */ #define AT_HWCAP 25 /* CPU feature flags. */ #define AT_HWCAP2 26 /* CPU feature flags 2. */ +#define AT_BSDFLAGS 27 /* ELF BSD Flags. */ -#define AT_COUNT 27 /* Count of defined aux entry types. */ +#define AT_COUNT 28 /* Count of defined aux entry types. */ /* * Relocation types. Index: sys/sparc64/include/elf.h =================================================================== --- sys/sparc64/include/elf.h +++ sys/sparc64/include/elf.h @@ -95,8 +95,9 @@ #define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */ #define AT_HWCAP 25 /* CPU feature flags. */ #define AT_HWCAP2 26 /* CPU feature flags 2. */ +#define AT_BSDFLAGS 27 /* ELF BSD Flags. */ -#define AT_COUNT 27 /* Count of defined aux entry types. */ +#define AT_COUNT 28 /* Count of defined aux entry types. */ /* Define "machine" characteristics */ #if __ELF_WORD_SIZE == 32 Index: sys/sys/elf_common.h =================================================================== --- sys/sys/elf_common.h +++ sys/sys/elf_common.h @@ -1342,5 +1342,6 @@ #define R_X86_64_TLSDESC 36 #define R_X86_64_IRELATIVE 37 +#define ELF_BSDF_FASTSIGBLK 0x0001 /* Kernel supports fast sigblock */ #endif /* !_SYS_ELF_COMMON_H_ */ Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h +++ sys/sys/proc.h @@ -302,6 +302,8 @@ uintptr_t td_rb_inact; /* (k) Current in-action mutex loc. */ struct syscall_args td_sa; /* (kx) Syscall parameters. Copied on fork for child tracing. */ + void *td_sigblock_ptr; /* (k) uptr for fast sigblock. */ + uint32_t td_sigblock_val; /* (k) fast sigblock value at #define td_endcopy td_pcb /* @@ -442,7 +444,7 @@ #define TDP_ALTSTACK 0x00000020 /* Have alternate signal stack. */ #define TDP_DEADLKTREAT 0x00000040 /* Lock acquisition - deadlock treatment. */ #define TDP_NOFAULTING 0x00000080 /* Do not handle page faults. */ -#define TDP_UNUSED9 0x00000100 /* --available-- */ +#define TDP_FAST_SIGBLOCK 0x00000100 /* Fast sigblock active */ #define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */ #define TDP_ITHREAD 0x00000400 /* Thread is an interrupt thread. */ #define TDP_SYNCIO 0x00000800 /* Local override, disable async i/o. */ @@ -465,6 +467,7 @@ #define TDP_UIOHELD 0x10000000 /* Current uio has pages held in td_ma */ #define TDP_FORKING 0x20000000 /* Thread is being created through fork() */ #define TDP_EXECVMSPC 0x40000000 /* Execve destroyed old vmspace */ +#define TDP_FAST_SIGPENDING 0x80000000 /* * Reasons that the current thread can not be run yet. Index: sys/sys/signalvar.h =================================================================== --- sys/sys/signalvar.h +++ sys/sys/signalvar.h @@ -254,6 +254,20 @@ /* Flags for ksi_flags */ #define SQ_INIT 0x01 +/* + * Fast_sigblock + */ +#define FAST_SIGBLOCK_SETPTR 1 +#define FAST_SIGBLOCK_UNBLOCK 2 +#define FAST_SIGBLOCK_UNSETPTR 3 + +#define FAST_SIGBLOCK_PEND 0x1 +#define FAST_SIGBLOCK_INC 0x10 + +#ifndef _KERNEL +int __sys_fast_sigblock(int cmd, void *ptr); +#endif + #ifdef _KERNEL /* Return nonzero if process p has an unmasked pending signal. */ @@ -363,6 +377,8 @@ int cursig(struct thread *td); void execsigs(struct proc *p); +void fetch_fast_sigblock(struct thread *td); +void fetch_fast_sigblock_failed(struct thread *td, int write); void gsignal(int pgid, int sig, ksiginfo_t *ksi); void killproc(struct proc *p, char *why); ksiginfo_t * ksiginfo_alloc(int wait); Index: sys/sys/sysctl.h =================================================================== --- sys/sys/sysctl.h +++ sys/sys/sysctl.h @@ -896,6 +896,7 @@ #define KERN_PROC_SIGTRAMP 41 /* signal trampoline location */ #define KERN_PROC_CWD 42 /* process current working directory */ #define KERN_PROC_NFDS 43 /* number of open file descriptors */ +#define KERN_PROC_FASTSIGBLK 44 /* address of fastsigblk magic word /* * KERN_IPC identifiers Index: sys/x86/include/elf.h =================================================================== --- sys/x86/include/elf.h +++ sys/x86/include/elf.h @@ -103,8 +103,9 @@ #define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */ #define AT_HWCAP 25 /* CPU feature flags. */ #define AT_HWCAP2 26 /* CPU feature flags 2. */ +#define AT_BSDFLAGS 27 /* ELF BSD Flags. */ -#define AT_COUNT 27 /* Count of defined aux entry types. */ +#define AT_COUNT 28 /* Count of defined aux entry types. */ /* * Relocation types. @@ -191,8 +192,9 @@ #define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */ #define AT_HWCAP 25 /* CPU feature flags. */ #define AT_HWCAP2 26 /* CPU feature flags 2. */ +#define AT_BSDFLAGS 27 /* ELF BSD Flags. */ -#define AT_COUNT 27 /* Count of defined aux entry types. */ +#define AT_COUNT 28 /* Count of defined aux entry types. */ /* * Relocation types. Index: usr.bin/procstat/procstat_sigs.c =================================================================== --- usr.bin/procstat/procstat_sigs.c +++ usr.bin/procstat/procstat_sigs.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -135,13 +136,17 @@ procstat_threads_sigs(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_proc *kip; + uintmax_t fastsigblk_addr; + int error, name[4], j, has_fastsigblk_addr; + pid_t pid; int j; unsigned int count, i; + size_t len; char *threadid; if ((procstat_opts & PS_OPT_NOHEADER) == 0) - xo_emit("{T:/%5s %6s %-16s %-7s %4s}\n", "PID", "TID", "COMM", - "SIG", "FLAGS"); + xo_emit("{T:/%5s %6s %-16s %-7s %4s %-18s}\n", "PID", "TID", "COMM", + "SIG", "FLAGS", "FSIGBLK"); kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, kipp->ki_pid, &count); @@ -153,6 +158,19 @@ kinfo_proc_sort(kip, count); for (i = 0; i < count; i++) { kipp = &kip[i]; + len = sizeof(fastsigblk_addr); + name[2] = KERN_PROC_FASTSIGBLK; + name[3] = kipp->ki_tid; + error = sysctl(name, 4, &fastsigblk_addr, &len, NULL, 0); + if (error < 0) { + if (errno != ESRCH && errno != ENOTTY) { + warn("sysctl: kern.proc.fastsigblk: %d", + kipp->ki_tid); + } + has_fastsigblk_addr = 0; + } else + has_fastsigblk_addr = 1; + asprintf(&threadid, "%d", kipp->ki_tid); if (threadid == NULL) xo_errc(1, ENOMEM, "Failed to allocate memory in " @@ -160,6 +178,7 @@ xo_open_container(threadid); xo_emit("{e:thread_id/%6d/%d}", kipp->ki_tid); xo_open_container("signals"); + for (j = 1; j <= _SIG_MAXSIG; j++) { xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid); xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid); @@ -168,6 +187,10 @@ xo_emit(" "); procstat_print_sig(&kipp->ki_siglist, j, 'P'); procstat_print_sig(&kipp->ki_sigmask, j, 'B'); + xo_emit(" "); + /* XXXKIB */ + xo_emit("{ek:%#jx/%#jx", has_fastsigblk_addr ? + (uintmax_t)fastsigblk_addr : -1); procstat_close_signame(j); xo_emit("\n"); }