forked from Minki/linux
34fa78b59c
The sigaddset/sigdelset/sigismember functions that are implemented with bitfield insn cannot allow the sigset argument to be placed in a data register since the sigset is wider than 32 bits. Remove the "d" constraint from the asm statements. The effect of the bug is that sending RT signals does not work, the signal number is truncated modulo 32. Signed-off-by: Andreas Schwab <schwab@linux-m68k.org> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Cc: stable@vger.kernel.org
97 lines
1.9 KiB
C
97 lines
1.9 KiB
C
#ifndef _M68K_SIGNAL_H
|
|
#define _M68K_SIGNAL_H
|
|
|
|
#include <uapi/asm/signal.h>
|
|
|
|
/* Most things should be clean enough to redefine this at will, if care
|
|
is taken to make libc match. */
|
|
|
|
#define _NSIG 64
|
|
#define _NSIG_BPW 32
|
|
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
|
|
|
|
typedef unsigned long old_sigset_t; /* at least 32 bits */
|
|
|
|
typedef struct {
|
|
unsigned long sig[_NSIG_WORDS];
|
|
} sigset_t;
|
|
|
|
struct old_sigaction {
|
|
__sighandler_t sa_handler;
|
|
old_sigset_t sa_mask;
|
|
unsigned long sa_flags;
|
|
__sigrestore_t sa_restorer;
|
|
};
|
|
|
|
struct sigaction {
|
|
__sighandler_t sa_handler;
|
|
unsigned long sa_flags;
|
|
__sigrestore_t sa_restorer;
|
|
sigset_t sa_mask; /* mask last for extensibility */
|
|
};
|
|
|
|
struct k_sigaction {
|
|
struct sigaction sa;
|
|
};
|
|
#include <asm/sigcontext.h>
|
|
|
|
#ifndef CONFIG_CPU_HAS_NO_BITFIELDS
|
|
#define __HAVE_ARCH_SIG_BITOPS
|
|
|
|
static inline void sigaddset(sigset_t *set, int _sig)
|
|
{
|
|
asm ("bfset %0{%1,#1}"
|
|
: "+o" (*set)
|
|
: "id" ((_sig - 1) ^ 31)
|
|
: "cc");
|
|
}
|
|
|
|
static inline void sigdelset(sigset_t *set, int _sig)
|
|
{
|
|
asm ("bfclr %0{%1,#1}"
|
|
: "+o" (*set)
|
|
: "id" ((_sig - 1) ^ 31)
|
|
: "cc");
|
|
}
|
|
|
|
static inline int __const_sigismember(sigset_t *set, int _sig)
|
|
{
|
|
unsigned long sig = _sig - 1;
|
|
return 1 & (set->sig[sig / _NSIG_BPW] >> (sig % _NSIG_BPW));
|
|
}
|
|
|
|
static inline int __gen_sigismember(sigset_t *set, int _sig)
|
|
{
|
|
int ret;
|
|
asm ("bfextu %1{%2,#1},%0"
|
|
: "=d" (ret)
|
|
: "o" (*set), "id" ((_sig-1) ^ 31)
|
|
: "cc");
|
|
return ret;
|
|
}
|
|
|
|
#define sigismember(set,sig) \
|
|
(__builtin_constant_p(sig) ? \
|
|
__const_sigismember(set,sig) : \
|
|
__gen_sigismember(set,sig))
|
|
|
|
static inline int sigfindinword(unsigned long word)
|
|
{
|
|
asm ("bfffo %1{#0,#0},%0"
|
|
: "=d" (word)
|
|
: "d" (word & -word)
|
|
: "cc");
|
|
return word ^ 31;
|
|
}
|
|
|
|
#endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */
|
|
|
|
#ifdef __uClinux__
|
|
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
|
|
#else
|
|
struct pt_regs;
|
|
extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
|
|
#endif /* __uClinux__ */
|
|
|
|
#endif /* _M68K_SIGNAL_H */
|