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_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..30a3ef0 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -273,6 +273,9 @@ struct thread { struct vm_map_entry *td_map_def_user; /* (k) Deferred entries. */ pid_t td_dbg_forked; /* (c) Child pid for debugger. */ u_int td_vp_reserv; /* (k) Count of reserved vnodes. */ + void *td_sigblock_ptr; /* (k) uptr for fast sigblock. */ + uint32_t td_sigblock_val; /* (k) fast sigblock value at + kernel entry. */ #define td_endzero td_sigmask /* Copied during fork1() or create_thread(). */ @@ -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);