diff options
author | gallatin <gallatin@FreeBSD.org> | 2000-11-13 20:44:05 +0000 |
---|---|---|
committer | gallatin <gallatin@FreeBSD.org> | 2000-11-13 20:44:05 +0000 |
commit | 30c1d926721383cc71c3cd1961eb34b5305f3753 (patch) | |
tree | 0ce323bc1848a6ced2f3c3627ba7e1eadac7b868 | |
parent | ae7cd02c4261982afb94655a8f92b2eac17f381a (diff) | |
download | FreeBSD-src-30c1d926721383cc71c3cd1961eb34b5305f3753.zip FreeBSD-src-30c1d926721383cc71c3cd1961eb34b5305f3753.tar.gz |
Make linux_sendsig and linux_sigreturn use all 64 bits of a
linux_sigset_t by updating the linux_sigframe struct so as to include
linux's "extramask" field. This field contains the upper 32-bits of
the sigset. extramask sits behind a linux_fpstate struct, which I've
defined primarily for padding purposes.
While we're here, define LINUX_NSIG in terms of LINUX_NBPW (32) and
LINUX_NSIG_WORDS (2).
This fixes problems where threaded apps would accumulate a large
number of zombies. This was happening because the exit signal resides
in the upper 32-bits of the sigset and was never getting unmasked by
the manager thread after the first child exited.
PR: misc/18530 (may be related, originator not yet contacted)
Reviewed by: marcel
-rw-r--r-- | sys/i386/linux/linux.h | 44 | ||||
-rw-r--r-- | sys/i386/linux/linux_sysvec.c | 17 |
2 files changed, 56 insertions, 5 deletions
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index 4ac9447..0795e6f 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -135,8 +135,10 @@ struct linux_new_utsname { #define LINUX_SIGPWR 30 #define LINUX_SIGUNUSED 31 -#define LINUX_NSIG 64 #define LINUX_SIGTBLSZ 31 +#define LINUX_NSIG_WORDS 2 +#define LINUX_NBPW 32 +#define LINUX_NSIG (LINUX_NBPW * LINUX_NSIG_WORDS) /* sigaction flags */ #define LINUX_SA_NOCLDSTOP 0x00000001 @@ -174,7 +176,7 @@ typedef void (*linux_handler_t)(int); typedef u_long linux_osigset_t; typedef struct { - u_int __bits[2]; + u_int __bits[LINUX_NSIG_WORDS]; } linux_sigset_t; typedef struct { @@ -289,6 +291,42 @@ typedef struct siginfo { #define lsi_band _sifields._sigpoll._band #define lsi_fd _sifields._sigpoll._fd +struct linux_fpreg { + u_int16_t significand[4]; + u_int16_t exponent; +}; + +struct linux_fpxreg { + u_int16_t significand[4]; + u_int16_t exponent; + u_int16_t padding[3]; +}; + +struct linux_xmmreg { + u_int32_t element[4]; +}; + +struct linux_fpstate { + /* Regular FPU environment */ + u_int32_t cw; + u_int32_t sw; + u_int32_t tag; + u_int32_t ipoff; + u_int32_t cssel; + u_int32_t dataoff; + u_int32_t datasel; + struct linux_fpreg _st[8]; + u_int16_t status; + u_int16_t magic; /* 0xffff = regular FPU data */ + + /* FXSR FPU environment */ + u_int32_t _fxsr_env[6]; /* env is ignored */ + u_int32_t mxcsr; + u_int32_t reserved; + struct linux_fpxreg _fxsr_st[8]; /* reg data is ignored */ + struct linux_xmmreg _xmm[8]; + u_int32_t padding[56]; +}; /* * We make the stack look like Linux expects it when calling a signal @@ -299,6 +337,8 @@ typedef struct siginfo { struct linux_sigframe { int sf_sig; struct linux_sigcontext sf_sc; + struct linux_fpstate fpstate; + u_int extramask[LINUX_NSIG_WORDS-1]; linux_handler_t sf_handler; }; diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index bf9161e..895a48c 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -345,7 +345,7 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) register struct trapframe *regs; struct linux_sigframe *fp, frame; struct sigacts *psp = p->p_sigacts; - int oonstack; + int oonstack, i; regs = p->p_md.md_regs; oonstack = p->p_sigstk.ss_flags & SS_ONSTACK; @@ -425,7 +425,10 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame.sf_sc.sc_ss = regs->tf_ss; frame.sf_sc.sc_err = regs->tf_err; frame.sf_sc.sc_trapno = code; /* XXX ???? */ - + bzero(&frame.fpstate, sizeof(struct linux_fpstate)); + for (i = 0; i < (LINUX_NSIG_WORDS-1); i++) + frame.extramask[i] = mask->__bits[i+1]; + if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal @@ -466,7 +469,9 @@ linux_sigreturn(p, args) { struct linux_sigcontext context; register struct trapframe *regs; - int eflags; + u_int extramask[LINUX_NSIG_WORDS-1]; + u_int *emp; + int eflags, i; regs = p->p_md.md_regs; @@ -513,6 +518,12 @@ linux_sigreturn(p, args) } p->p_sigstk.ss_flags &= ~SS_ONSTACK; + emp = (u_int *)((caddr_t)args->scp + sizeof(context) + + sizeof(struct linux_fpstate)); + if (copyin((caddr_t)emp, extramask, sizeof(extramask)) == 0) + for (i = 0; i < (LINUX_NSIG_WORDS-1); i++) + p->p_sigmask.__bits[i+1] = extramask[i]; + SIGSETOLD(p->p_sigmask, context.sc_mask); SIG_CANTMASK(p->p_sigmask); |