| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 | 	All what you never wanted to know about sigaction(),	struct sigaction, and sigset_t.Before vda started messing with sigset_t, struct sigactionand sigaction() functions, things looked this way:	StructuresMIPS:Ignoring bogus "#if defined(__mips__) ..." block inlibc/sysdeps/linux/common/bits/kernel_sigaction.hand usinglibc/sysdeps/linux/mips/bits/kernel_sigaction.has an authoritative source:HAVE_SA_RESTORER is #definedstruct old_kernel_sigaction {        unsigned      sa_flags;        sighandler_t  k_sa_handler;        unsigned long sa_mask;        unsigned      pad0[3]; /* reserved, keep size constant */        /* Abi says here follows reserved int[2] */        void          (*sa_restorer)(void);#if (_MIPS_SZPTR < 64)        /* For 32 bit code we have to pad struct sigaction to get         * constant size for the ABI */        int           pad1[1]; /* reserved */#endif};struct kernel_sigaction {        unsigned int  sa_flags;        sighandler_t  k_sa_handler;        kernel_sigset_t sa_mask;        void          (*sa_restorer)(void);        int           s_resv[1]; /* reserved */};struct sigaction {	unsigned      sa_flags;	sighandler_t  sa_handler;	sigset_t      sa_mask;	/* The ABI says here are two unused ints following. */	/* Restore handler.  */	void          (*sa_restorer)(void);#if _MIPS_SZPTR < 64	int           sa_resv[1];#endif};IA64:Has no old_sigaction. What a relief.struct kernel_sigaction {        sighandler_t  k_sa_handler;        unsigned long sa_flags;        sigset_t      sa_mask;};struct sigaction {	sighandler_t  sa_handler;	unsigned long sa_flags;	sigset_t      sa_mask;};Alpha:struct old_kernel_sigaction {	sighandler_t  k_sa_handler;	unsigned long sa_mask;	unsigned      sa_flags;};struct kernel_sigaction {	sighandler_t  k_sa_handler;	unsigned      sa_flags;	sigset_t      sa_mask;};struct sigaction {	sighandler_t  sa_handler;	sigset_t      sa_mask;	unsigned      sa_flags;};HPPA:struct kernel_sigaction {	sighandler_t  k_sa_handler;	unsigned long sa_flags;	sigset_t      sa_mask;};struct sigaction {	sighandler_t  sa_handler;	unsigned long sa_flags;	sigset_t      sa_mask;};The rest, kernel side:HAVE_SA_RESTORER #definedstruct old_kernel_sigaction {	sighandler_t  k_sa_handler;	unsigned long sa_mask;	unsigned long sa_flags;	void          (*sa_restorer)(void);};struct kernel_sigaction {	sighandler_t  k_sa_handler;	unsigned long sa_flags;	void          (*sa_restorer)(void);	sigset_t      sa_mask;};On userspace side, Sparc has special struct sigaction:struct sigaction {	sighandler_t  sa_handler;	sigset_t      sa_mask;	unsigned long sa_flags;	void          (*sa_restorer)(void); /* Not used by Linux/Sparc */};And finally the rest has:struct sigaction {	sighandler_t  sa_handler;	sigset_t      sa_mask;	int           sa_flags;	void          (*sa_restorer)(void);};Userspace sigset_t was uniformly defined as vector of longsbig enough to hold 1024 (!) bits - carried over from glibc.Since the only arch whose struct kernel_sigaction contains sa_masknot as a last member is MIPS, MIPS has special kernel_sigset_t,which is an array of longs long enough for 128 bits.Other arches still used userspace sigset_t in struct kernel_sigaction,but it did not really matter because overlong kernel_sigactiondoes not hurt in sigaction() [explained below].On kernel side, all arches define _NSIG to 65 (meaningthere are 64 signals, 1..64) except MIPS, which define it to 129.	Functionssigaction() [libc function] usually has two kernel_sigaction'son stack and copy (userspace) struct sigaction members intofirst one, executes syscall, then pulls out the result fromsecond one. This accomodates differences in layouts of structs.The only typically present quirk is what to do with sa_restorer.    libc/sysdeps/linux/arm/sigaction.cif HAVE_SA_RESTORER and (sa_flags & SA_RESTORER) is not set,sets sa_restorer to(flags & SA_SIGINFO) ? __default_rt_sa_restorer : __default_sa_restorer,and sets SA_RESTORER,otherwise passes it as-is. Which is kinda strange, because AFAICSHAVE_SA_RESTORER is *not* defined for ARM.    libc/sysdeps/linux/i386/sigaction.cForcibly sets SA_RESTORER and sa_restorer:kact.sa_flags = act->sa_flags | SA_RESTORER;kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) ? &restore_rt : &restore);    libc/sysdeps/linux/x86_64/sigaction.cForcibly sets SA_RESTORER and sa_restorer:kact.sa_flags = act->sa_flags | SA_RESTORER;kact.sa_restorer = &restore_rt;    libc/sysdeps/linux/mips/sigaction.c# ifdef HAVE_SA_RESTORER#  if _MIPS_SIM == _ABIO32                kact.sa_restorer = act->sa_restorer;#  else                kact.sa_restorer = &restore_rt;#  endif# endifNo confusion here, HAVE_SA_RESTORER is #defined for MIPS    libc/sysdeps/linux/avr32/sigaction.cif (kact.sa_flags & SA_RESTORER) {        kact.sa_restorer = act->sa_restorer;} else {        kact.sa_restorer = __default_rt_sa_restorer;	kact.sa_flags |= SA_RESTORER;}Does not check HAVE_SA_RESTORER, but avr32 fallsin "completely ordinary" category on both kernel anduserspace sides, and those have it defined.    libc/sysdeps/linux/xtensa/sigaction.cif (kact.sa_flags & SA_RESTORER) {        kact.sa_restorer = act->sa_restorer;} else {        kact.sa_restorer = __default_sa_restorer;	kact.sa_flags |= SA_RESTORER;}Thus, similar to avr32.    libc/signal/sigaction.c (i.e. the all other arches)# ifdef HAVE_SA_RESTORER        kact.sa_restorer = act->sa_restorer;# endifPlain translation, just sa_restorer copy is protectedby HAVE_SA_RESTORER #define check. Looks like hereHAVE_SA_RESTORER will be undef'ed only for IA64,Alpha an HPPA.	Proposed overhaul past 0.9.30Since we can define libc-side structures at will:make sigset_t and struct sigaction identical on kernel side and libc sidewithin each arch. If arches do not need special handling of sa_restorer,then sigaction() can directly use passed struct sigaction as-is.Otherwise, a copy is still needed, although sigaction() might havejust one struct kernel_sigaction on stack and use it both for passingdata to kernel and for receiving it back. Might save a few bytes.To this effect:* Make sigset_t size match kernel side on all arches.  This is easy since all arches have 64 signals and only MIPS has 128.* Modify libc/sysdeps/linux/$ARCH/bits/sigaction.h  so that its struct sigaction matches kernel's. If sa_restorer  field is present in libc but is missing in kernel_sigaction,  add it at the bottom in order to not mess up kernel_sigaction layout.* Modify libc/sysdeps/linux/$ARCH/sigaction.c  to implement the logic above. In "common" pseudo-arch  (libc/signal/sigaction.c file),  we would not even need to do any copying, as described above.* Document discovered arch quirks while debugging this mess.* struct old_kernel_sigaction can't be disposed of in a similar way,  we need to have userspace struct sigaction unchanged regardless  whether we use "old" or "new" kernel sigaction() syscall.  It's moot anyway because "old" one is long unused, it's from  pre-2.2 kernels.
 |