While the userspace function signature is
int sigsuspend(const sigset_t *maskptr)
there are several variants of how this is mapped into kernel
functions: one for rt_sigsuspend and several, mutually incompatible,
legacy ones, split by architectures. Before this commit, klibc did
not care about that and passed maskptr as first and only argument
to the syscall, leading to junk in other argument slots. There are
several non-RT variants:
1) int sigsuspend(sigset_t mask)
2) long sigsuspend(sigset_t mask)
3) int sigsuspend(int ignored1,
unsigned long ignored2, sigset_t mask)
4) int sigsuspend(int ignored1, int ignored2, sigset_t mask)
5) long sigsuspend(int ignored1, int ignored2, sigset_t mask)
Note how none of these accepts a pointer, they all want the value.
6) (none at all, only RT exists)
Breakdown by architectures:
alpha (2+6) not affected: using RT already
amd64 (6) not affected by this patch
arm (3) changed
blackfin (6) non-RT stubbed out [not in klibc]
cris (1) changed
frv (4) [not in klibc]
h8300 (7) see below [not in klibc]
i386 (4) changed
ia64 (6) not affected by this patch
m32r (6) not affected by this patch
m68k (4) changed
microblaze (6) non-RT stubbed out [not in klibc]
mips (8) see below, switched to RT
mips64 (8) see below, switched to RT
mn10300 (5) [not in klibc]
parisc (6) not affected by this patch
ppc (2) changed
ppc64 (6) not affected by this patch
s390 (5) changed
sh (1) changed
sparc (1+6) not affected: using RT already
sparc64 (1+6) not affected: using RT already
All architectures not listed do not have any non-RT sigsuspend.
(7) I could, for the hell of it, not figure out what the calling
convention on this architecture was. But it?s not in klibc.
(8) I could not figure out the calling convention either, but
the architecture headers seem to work with RT, so switched
to RT. Furthermore, its sigset_t seems to be 128 bit wide.
Signed-off-by: Thorsten Glaser <tg at mirbsd.org>
---
usr/include/arch/alpha/klibc/archconfig.h | 2 ++
usr/include/arch/arm/klibc/archconfig.h | 2 ++
usr/include/arch/cris/klibc/archconfig.h | 2 ++
usr/include/arch/i386/klibc/archconfig.h | 2 ++
usr/include/arch/m68k/klibc/archconfig.h | 2 ++
usr/include/arch/mips/klibc/archconfig.h | 3 +++
usr/include/arch/mips64/klibc/archconfig.h | 3 +++
usr/include/arch/ppc/klibc/archconfig.h | 2 ++
usr/include/arch/s390/klibc/archconfig.h | 2 ++
usr/include/arch/sh/klibc/archconfig.h | 2 ++
usr/include/arch/sparc/klibc/archconfig.h | 2 ++
usr/include/arch/sparc64/klibc/archconfig.h | 2 ++
usr/klibc/SYSCALLS.def | 13 ++++++++++-
usr/klibc/sigsuspend.c | 31 +++++++++++++++++++++++++++
14 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/usr/include/arch/alpha/klibc/archconfig.h
b/usr/include/arch/alpha/klibc/archconfig.h
index 272fee0..cb5c854 100644
--- a/usr/include/arch/alpha/klibc/archconfig.h
+++ b/usr/include/arch/alpha/klibc/archconfig.h
@@ -12,4 +12,6 @@
#define _KLIBC_USE_RT_SIG 1
#define _KLIBC_STATFS_F_TYPE_64 0
+#define _KLIBC_SIGSUSPEND_L_1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/arm/klibc/archconfig.h
b/usr/include/arch/arm/klibc/archconfig.h
index 36e9ab5..e18145b 100644
--- a/usr/include/arch/arm/klibc/archconfig.h
+++ b/usr/include/arch/arm/klibc/archconfig.h
@@ -15,4 +15,6 @@
# define _KLIBC_ARM_USE_BX 1
#endif
+#define _KLIBC_SIGSUSPEND_I_IUL1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/cris/klibc/archconfig.h
b/usr/include/arch/cris/klibc/archconfig.h
index 0206078..176de6c 100644
--- a/usr/include/arch/cris/klibc/archconfig.h
+++ b/usr/include/arch/cris/klibc/archconfig.h
@@ -12,4 +12,6 @@
/* cris uses 13 as the page shift factor for sys_mmap2 */
#define _KLIBC_MMAP2_SHIFT 13
+#define _KLIBC_SIGSUSPEND_I_1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/i386/klibc/archconfig.h
b/usr/include/arch/i386/klibc/archconfig.h
index b409a21..e42bee7 100644
--- a/usr/include/arch/i386/klibc/archconfig.h
+++ b/usr/include/arch/i386/klibc/archconfig.h
@@ -12,4 +12,6 @@
/* The i386 <asm/signal.h> is still not clean enough for this... */
#define _KLIBC_USE_RT_SIG 0
+#define _KLIBC_SIGSUSPEND_I_II1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/m68k/klibc/archconfig.h
b/usr/include/arch/m68k/klibc/archconfig.h
index 10ef62e..71b5378 100644
--- a/usr/include/arch/m68k/klibc/archconfig.h
+++ b/usr/include/arch/m68k/klibc/archconfig.h
@@ -12,4 +12,6 @@
/* On m68k, sys_mmap2 uses the current page size as the shift factor */
#define _KLIBC_MMAP2_SHIFT __getpageshift()
+#define _KLIBC_SIGSUSPEND_I_II1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/mips/klibc/archconfig.h
b/usr/include/arch/mips/klibc/archconfig.h
index ff0afb5..194fee1 100644
--- a/usr/include/arch/mips/klibc/archconfig.h
+++ b/usr/include/arch/mips/klibc/archconfig.h
@@ -18,4 +18,7 @@
/* MIPS has nonstandard socket definitions */
#define _KLIBC_HAS_ARCHSOCKET_H 1
+/* signal.h seems clean enough for RT signals; non-RT are broken */
+#define _KLIBC_USE_RT_SIG 1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/mips64/klibc/archconfig.h
b/usr/include/arch/mips64/klibc/archconfig.h
index 9071cb4..a26addc 100644
--- a/usr/include/arch/mips64/klibc/archconfig.h
+++ b/usr/include/arch/mips64/klibc/archconfig.h
@@ -12,4 +12,7 @@
/* MIPS has nonstandard socket definitions */
#define _KLIBC_HAS_ARCHSOCKET_H 1
+/* signal.h seems clean enough for RT signals; non-RT are broken */
+#define _KLIBC_USE_RT_SIG 1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/ppc/klibc/archconfig.h
b/usr/include/arch/ppc/klibc/archconfig.h
index ce04eee..0f618f9 100644
--- a/usr/include/arch/ppc/klibc/archconfig.h
+++ b/usr/include/arch/ppc/klibc/archconfig.h
@@ -11,4 +11,6 @@
/* All defaults */
+#define _KLIBC_SIGSUSPEND_L_1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/s390/klibc/archconfig.h
b/usr/include/arch/s390/klibc/archconfig.h
index d7a71a4..d58ad40 100644
--- a/usr/include/arch/s390/klibc/archconfig.h
+++ b/usr/include/arch/s390/klibc/archconfig.h
@@ -12,4 +12,6 @@
/* Both s390 and s390x use the "32-bit" version of this structure */
#define _KLIBC_STATFS_F_TYPE_64 0
+#define _KLIBC_SIGSUSPEND_L_II1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/sh/klibc/archconfig.h
b/usr/include/arch/sh/klibc/archconfig.h
index 9c9e3d8..f4a5f90 100644
--- a/usr/include/arch/sh/klibc/archconfig.h
+++ b/usr/include/arch/sh/klibc/archconfig.h
@@ -11,4 +11,6 @@
/* All defaults */
+#define _KLIBC_SIGSUSPEND_I_1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/sparc/klibc/archconfig.h
b/usr/include/arch/sparc/klibc/archconfig.h
index 70d5ef0..eb71ad0 100644
--- a/usr/include/arch/sparc/klibc/archconfig.h
+++ b/usr/include/arch/sparc/klibc/archconfig.h
@@ -12,4 +12,6 @@
#define _KLIBC_USE_RT_SIG 1 /* Use rt_* signals */
#define _KLIBC_SYS_SOCKETCALL 1 /* Use sys_socketcall unconditionally */
+#define _KLIBC_SIGSUSPEND_I_1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/sparc64/klibc/archconfig.h
b/usr/include/arch/sparc64/klibc/archconfig.h
index 794d15b..f866438 100644
--- a/usr/include/arch/sparc64/klibc/archconfig.h
+++ b/usr/include/arch/sparc64/klibc/archconfig.h
@@ -13,4 +13,6 @@
#define _KLIBC_NEEDS_SA_RESTORER 1 /* Need a restorer function */
#define _KLIBC_SYS_SOCKETCALL 1 /* Use sys_socketcall unconditionally */
+#define _KLIBC_SIGSUSPEND_L_1
+
#endif /* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def
index 6ed6bdf..7abab15 100644
--- a/usr/klibc/SYSCALLS.def
+++ b/usr/klibc/SYSCALLS.def
@@ -206,9 +206,20 @@ int rt_sigprocmask::__rt_sigprocmask(int, const sigset_t *,
sigset_t *, size_t);
<sparc64> void rt_sigreturn::__sigreturn();
#else
int sigaction::__sigaction(int, const struct sigaction *, struct sigaction *);
-int sigsuspend(const sigset_t *);
int sigpending(sigset_t *);
int sigprocmask(int, const sigset_t *, sigset_t *);
+/*
+ * There is no single calling convention for the old sigsuspend.
+ * If your architecture is not listed here, building klibc shall
+ * rather fail than use a broken calling convention.
+ * You better switch to RT signals on those architectures:
+ * blackfin h8300 microblaze mips
+ */
+<cris,sh,sparc> int sigsuspend::__n_sigsuspend(sigset_t);
+<alpha,powerpc,sparc64> long sigsuspend::__n_sigsuspend(sigset_t);
+<arm> int sigsuspend::__n_sigsuspend(int, unsigned long, sigset_t);
+<frv,i386,m68k> int sigsuspend::__n_sigsuspend(int, int, sigset_t);
+<mn10300,s390> long sigsuspend::__n_sigsuspend(int, int, sigset_t);
#endif
int kill(pid_t, int);
<?> unsigned int alarm(unsigned int);
diff --git a/usr/klibc/sigsuspend.c b/usr/klibc/sigsuspend.c
index 4d910d5..51cdc91 100644
--- a/usr/klibc/sigsuspend.c
+++ b/usr/klibc/sigsuspend.c
@@ -15,4 +15,35 @@ int sigsuspend(const sigset_t * mask)
return __rt_sigsuspend(mask, sizeof *mask);
}
+#else
+
+#if defined(_KLIBC_SIGSUSPEND_I_1)
+extern int __n_sigsuspend(sigset_t);
+#define SIGSUSPEND_1
+#elif defined(_KLIBC_SIGSUSPEND_L_1)
+extern long __n_sigsuspend(sigset_t);
+#define SIGSUSPEND_1
+#elif defined(_KLIBC_SIGSUSPEND_I_II1)
+extern int __n_sigsuspend(int, int, sigset_t);
+#define SIGSUSPEND_001
+#elif defined(_KLIBC_SIGSUSPEND_L_II1)
+extern long __n_sigsuspend(int, int, sigset_t);
+#define SIGSUSPEND_001
+#elif defined(_KLIBC_SIGSUSPEND_I_IUL1)
+extern int __n_sigsuspend(int, unsigned long, sigset_t);
+#define SIGSUSPEND_001
+#else
+#error unknown architecture
+#endif
+
+int
+sigsuspend(const sigset_t *maskp)
+{
+#ifdef SIGSUSPEND_1
+ return ((int)__n_sigsuspend(*maskp));
+#else
+ return ((int)__n_sigsuspend(0, 0, *maskp));
+#endif
+}
+
#endif
--
1.7.10