diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index babae30..d36c66d 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -550,6 +550,7 @@ FBSDprivate_1.0 { __sys_extattr_set_link; _extattrctl; __sys_extattrctl; + __sys_fast_sigblock; _fchdir; __sys_fchdir; _fchflags; diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index bb790dd..5d34ea9 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -235,6 +235,7 @@ int tls_dtv_generation = 1; /* Used to detect when dtv size changes */ int tls_max_index = 1; /* Largest module index allocated */ bool ld_library_path_rpath = false; +bool ld_fast_sigblock = false; /* * Fill in a DoneList with an allocation large enough to hold all of @@ -384,6 +385,10 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) ((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(); diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index 0aba7cd..d239b9b 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -353,6 +353,7 @@ void *xmalloc(size_t); char *xstrdup(const char *); extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; extern Elf_Sym sym_zero; /* For resolving undefined weak refs. */ +extern bool ld_fast_sigblock; void dump_relocations(Obj_Entry *); void dump_obj_relocations(Obj_Entry *); diff --git a/libexec/rtld-elf/rtld_lock.c b/libexec/rtld-elf/rtld_lock.c index d1563e5..7d73dd8 100644 --- a/libexec/rtld-elf/rtld_lock.c +++ b/libexec/rtld-elf/rtld_lock.c @@ -43,6 +43,7 @@ */ #include +#include #include #include #include @@ -61,6 +62,7 @@ typedef struct Struct_Lock { static sigset_t fullsigmask, oldsigmask; static int thread_flag; +static uint32_t fsigblock; static void * def_lock_create() @@ -111,31 +113,53 @@ def_rlock_acquire(void *lock) } static void -def_wlock_acquire(void *lock) +sig_fastunblock(void) { - Lock *l = (Lock *)lock; - sigset_t tmp_oldsigmask; + uint32_t oldval; - for ( ; ; ) { - sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask); - if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG)) - break; - sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL); - } - oldsigmask = tmp_oldsigmask; + 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_lock_release(void *lock) +def_wlock_acquire(void *lock) { - Lock *l = (Lock *)lock; + Lock *l = (Lock *)lock; + sigset_t tmp_oldsigmask; + + if (ld_fast_sigblock) { + for (;;) { + atomic_add_rel_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); + } + oldsigmask = tmp_oldsigmask; + } +} - if ((l->lock & WAFLAG) == 0) - atomic_add_rel_int(&l->lock, -RC_INCR); - else { - atomic_add_rel_int(&l->lock, -WAFLAG); - sigprocmask(SIG_SETMASK, &oldsigmask, NULL); - } +static void +def_lock_release(void *lock) +{ + Lock *l = (Lock *)lock; + + if ((l->lock & WAFLAG) == 0) + atomic_add_rel_int(&l->lock, -RC_INCR); + else { + atomic_add_rel_int(&l->lock, -WAFLAG); + if (ld_fast_sigblock) + sig_fastunblock(); + else + sigprocmask(SIG_SETMASK, &oldsigmask, NULL); + } } static int @@ -286,19 +310,24 @@ lockdflt_init() 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); + } } /* @@ -319,7 +348,10 @@ _rtld_thread_init(struct RtldLockInfo *pli) 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) diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h index d69c6b4..4393aa8 100644 --- a/sys/amd64/include/elf.h +++ b/sys/amd64/include/elf.h @@ -96,8 +96,9 @@ __ElfType(Auxinfo); #define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ #define AT_STACKPROT 23 /* Initial stack protection. */ +#define AT_BSDFLAGS 25 /* ELF BSD Flags. */ -#define AT_COUNT 24 /* Count of defined aux entry types. */ +#define AT_COUNT 26 /* Count of defined aux entry types. */ /* * Relocation types. diff --git a/sys/arm/include/elf.h b/sys/arm/include/elf.h index 91086f8..4cea38e 100644 --- a/sys/arm/include/elf.h +++ b/sys/arm/include/elf.h @@ -84,8 +84,9 @@ __ElfType(Auxinfo); #define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ #define AT_STACKPROT 23 /* Initial stack protection. */ +#define AT_BSDFLAGS 25 /* ELF BSD Flags. */ -#define AT_COUNT 24 /* Count of defined aux entry types. */ +#define AT_COUNT 26 /* Count of defined aux entry types. */ #define R_ARM_COUNT 33 /* Count of defined relocation types. */ diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 4106447..949ca2a 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -1004,4 +1004,4 @@ int *status, int options, \ struct wrusage32 *wrusage, \ siginfo_t *info); } - +533 AUE_NULL NOPROTO { int fast_sigblock(int cmd, uint32_t *ptr); } diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h index 93fa1fd..a6e419d 100644 --- a/sys/i386/include/elf.h +++ b/sys/i386/include/elf.h @@ -98,8 +98,9 @@ __ElfType(Auxinfo); #define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ #define AT_STACKPROT 23 /* Initial stack protection. */ +#define AT_BSDFLAGS 25 /* ELF BSD flags. */ -#define AT_COUNT 24 /* Count of defined aux entry types. */ +#define AT_COUNT 26 /* Count of defined aux entry types. */ /* * Relocation types. diff --git a/sys/ia64/include/elf.h b/sys/ia64/include/elf.h index 34135ac..43cf946 100644 --- a/sys/ia64/include/elf.h +++ b/sys/ia64/include/elf.h @@ -97,8 +97,9 @@ __ElfType(Auxinfo); #define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ #define AT_STACKPROT 23 /* Initial stack protection. */ +#define AT_BSDFLAGS 25 /* ELF BSD Flags. */ -#define AT_COUNT 24 /* Count of defined aux entry types. */ +#define AT_COUNT 26 /* Count of defined aux entry types. */ /* * Values for e_flags. diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 4c1cb5b..f3c4109 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -1020,6 +1020,7 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp) AUXARGS_ENTRY(pos, AT_STACKPROT, imgp->sysent->sv_shared_page_obj != NULL && imgp->stack_prot != 0 ? imgp->stack_prot : imgp->sysent->sv_stackprot); + AUXARGS_ENTRY(pos, AT_BSDFLAGS, ELF_BSDF_FASTSIGBLK); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index a37b9f1..740642a 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1012,6 +1012,7 @@ exec_new_vmspace(imgp, sv) int error; struct proc *p = imgp->proc; struct vmspace *vmspace = p->p_vmspace; + struct thread *td = curthread; vm_object_t obj; vm_offset_t sv_minuser, stack_addr; vm_map_t map; @@ -1020,6 +1021,10 @@ exec_new_vmspace(imgp, sv) 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); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 0d2709f..463b055 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -573,7 +573,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * been preserved. */ p2->p_flag |= p1->p_flag & P_SUGID; - td2->td_pflags |= td->td_pflags & TDP_ALTSTACK; + td2->td_pflags |= td->td_pflags & (TDP_ALTSTACK | TDP_FAST_SIGBLOCK); SESS_LOCK(p1->p_session); if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) p2->p_flag |= P_CONTROLT; diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 2a74a59..760a971 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -2597,6 +2597,77 @@ errout: 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| @@ -2705,3 +2776,7 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_UMASK, umask, CTLFLAG_RD | static SYSCTL_NODE(_kern_proc, KERN_PROC_OSREL, osrel, CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_osrel, "Process binary osreldate"); + +static SYSCTL_NODE(_kern_proc, KERN_PROC_FASTSIGBLK, fastsigblk, CTLFLAG_RD | + CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_fastsigblk, + "Thread fast_sigblock address"); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 9c52707..8d86aa24 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -235,6 +235,7 @@ static int sigproptbl[NSIG] = { }; static void reschedule_signals(struct proc *p, sigset_t block, int flags); +static sigset_t fastblock_mask; static void sigqueue_start(void) @@ -245,6 +246,16 @@ sigqueue_start(void) 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 * @@ -2565,6 +2576,24 @@ issignal(struct thread *td, int stop_allowed) 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); + } + } + sig = sig_ffs(&sigpending); if (p->p_stops & S_SIG) { @@ -3438,3 +3467,92 @@ sigacts_shared(struct sigacts *ps) mtx_unlock(&ps->ps_mtx); return (shared); } + +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); +} diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c index 3d6dc5a..15374b9 100644 --- a/sys/kern/subr_syscall.c +++ b/sys/kern/subr_syscall.c @@ -130,6 +130,12 @@ syscallenter(struct thread *td, struct syscall_args *sa) sa->callp, sa->args, 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); diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index 22cabcb..890b2e1 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -193,8 +193,8 @@ ast(struct trapframe *framep) { struct thread *td; struct proc *p; - int flags; - int sig; + uint32_t oldval; + int flags, sig; td = curthread; p = td->td_proc; @@ -270,6 +270,7 @@ ast(struct trapframe *framep) */ 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, SIG_STOP_ALLOWED)) != 0) @@ -277,6 +278,25 @@ ast(struct trapframe *framep) 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. diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 148dea3..1ca0e54 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -955,5 +955,6 @@ int *status, int options, \ struct __wrusage *wrusage, \ siginfo_t *info); } +533 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 diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h index be4d024..b0ef351 100644 --- a/sys/mips/include/elf.h +++ b/sys/mips/include/elf.h @@ -280,8 +280,9 @@ __ElfType(Auxinfo); #define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ #define AT_STACKPROT 23 /* Initial stack protection. */ +#define AT_BSDFLAGS 25 /* ELF BSD Flags. */ -#define AT_COUNT 24 /* Count of defined aux entry types. */ +#define AT_COUNT 26 /* Count of defined aux entry types. */ #define ET_DYN_LOAD_ADDR 0x0120000 diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h index 0e81b4a..f5fc287 100644 --- a/sys/powerpc/include/elf.h +++ b/sys/powerpc/include/elf.h @@ -107,8 +107,9 @@ __ElfType(Auxinfo); #define AT_PAGESIZESLEN 19 /* Number of pagesizes. */ #define AT_STACKPROT 21 /* Initial stack protection. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ +#define AT_BSDFLAGS 23 /* ELF BSD Flags. */ -#define AT_COUNT 23 /* Count of defined aux entry types. */ +#define AT_COUNT 24 /* Count of defined aux entry types. */ /* * Relocation types. diff --git a/sys/sparc64/include/elf.h b/sys/sparc64/include/elf.h index 448ca66..f88ed21 100644 --- a/sys/sparc64/include/elf.h +++ b/sys/sparc64/include/elf.h @@ -92,8 +92,9 @@ __ElfType(Auxinfo); #define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ #define AT_STACKPROT 23 /* Initial stack protection. */ +#define AT_BSDFLAGS 25 /* ELF BSD Flags. */ -#define AT_COUNT 24 /* Count of defined aux entry types. */ +#define AT_COUNT 26 /* Count of defined aux entry types. */ /* Define "machine" characteristics */ #if __ELF_WORD_SIZE == 32 diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index 8f02ef1..f8b4a9c 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -973,5 +973,6 @@ typedef struct { #define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ #define R_X86_64_IRELATIVE 37 +#define ELF_BSDF_FASTSIGBLK 0x0001 /* Kernel supports fast sigblock */ #endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 78af5c0..65a96f8 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -284,6 +284,9 @@ struct thread { u_char td_pri_class; /* (t) Scheduling class. */ u_char td_user_pri; /* (t) User pri from estcpu and nice. */ u_char td_base_user_pri; /* (t) Base user pri */ + void *td_sigblock_ptr; /* (k) uptr for fast sigblock. */ + uint32_t td_sigblock_val; /* (k) fast sigblock value at + kernel entry. */ #define td_endcopy td_pcb /* @@ -425,6 +428,8 @@ do { \ #define TDP_RESETSPUR 0x04000000 /* Reset spurious page fault history. */ #define TDP_NERRNO 0x08000000 /* Last errno is already in td_errno */ #define TDP_UIOHELD 0x10000000 /* Current uio has pages held in td_ma */ +#define TDP_FAST_SIGBLOCK 0x20000000 /* Fast sigblock active */ +#define TDP_FAST_SIGPENDING 0x40000000 /* * Reasons that the current thread can not be run yet. diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index 71685e7..68cca58 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -250,6 +250,20 @@ typedef struct sigqueue { /* 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. */ @@ -329,6 +343,8 @@ extern struct mtx sigio_lock; int cursig(struct thread *td, int stop_allowed); 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); diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index e575f22..1e36359 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -568,6 +568,8 @@ SYSCTL_ALLOWED_TYPES(UINT64, uint64_t *a; unsigned long long *b; ); #define KERN_PROC_PS_STRINGS 38 /* get ps_strings location */ #define KERN_PROC_UMASK 39 /* process umask */ #define KERN_PROC_OSREL 40 /* osreldate for process binary */ +#define KERN_PROC_FASTSIGBLK 41 /* address of fastsigblk magic word + location, ENOTTY if not enabled */ /* * KERN_IPC identifiers diff --git a/usr.bin/procstat/procstat_sigs.c b/usr.bin/procstat/procstat_sigs.c index 70df250..8c71014 100644 --- a/usr.bin/procstat/procstat_sigs.c +++ b/usr.bin/procstat/procstat_sigs.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -90,14 +91,15 @@ procstat_threads_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp) { struct kinfo_proc *kip; pid_t pid; - int error, name[4], j; + uintmax_t fastsigblk_addr; + int error, name[4], j, has_fastsigblk_addr; unsigned int i; size_t len; pid = kipp->ki_pid; if (!hflag) - printf("%5s %6s %-16s %-7s %4s\n", "PID", "TID", "COMM", - "SIG", "FLAGS"); + printf("%5s %6s %-16s %-7s %5s %9s\n", "PID", "TID", "COMM", + "SIG", "FLAGS", "FASTSIGBLK"); /* * We need to re-query for thread information, so don't use *kipp. @@ -129,6 +131,19 @@ procstat_threads_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp) kinfo_proc_sort(kip, len / sizeof(*kipp)); for (i = 0; i < len / sizeof(*kipp); 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; for (j = 1; j <= _SIG_MAXSIG; j++) { printf("%5d ", pid); printf("%6d ", kipp->ki_tid); @@ -137,6 +152,11 @@ procstat_threads_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp) printf(" "); procstat_print_sig(&kipp->ki_siglist, j, 'P'); procstat_print_sig(&kipp->ki_sigmask, j, 'B'); + printf(" "); + if (has_fastsigblk_addr) + printf("%#jx", (uintmax_t)fastsigblk_addr); + else + printf("-"); printf("\n"); } }