2005-11-16 20:31:58

by Constantine Gavrilov

[permalink] [raw]
Subject: gcc optimizer miscompiles code with sigaddset on i386 ?

/***************************************************************************
sigset_test.c - description
-------------------
begin : Wed Nov 16 2005
copyright : (C) 2005 by Qlusters Ltd
email : [email protected]
***************************************************************************/
#ifdef DEF_KERNEL
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/signal.h>

static int sigset_test_init(void);
static void sigset_test_exit(void);

module_init(sigset_test_init);
module_exit(sigset_test_exit);
#define SIGADDSET sigaddset
#define SIGISMEMBER sigismember
//#define SIGADDSET(x, y) set_bit(y, (long *)x)

#else
extern int printf(const char *format, ...);
#define printk printf
#define KERN_INFO
typedef struct {
unsigned long sig[2];
} sigset_t;
#include <asm/signal.h>
#define _NSIG (64)
#define _NSIG_BPW (32)

static __inline__ void SIGADDSET(sigset_t *set, int _sig)
{
__asm__("btsl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "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__("btl %2,%1\n\tsbbl %0,%0"
: "=r"(ret) : "m"(*set), "Ir"(_sig-1) : "cc");
return ret;
}

#define SIGISMEMBER(set,sig) \
(__builtin_constant_p(sig) ? \
__const_sigismember((set),(sig)) : \
__gen_sigismember((set),(sig)))

#endif



sigset_t ssi_fatal_sigset;
static sigset_t ssi_stop_set;
static void print_pending_signals(sigset_t *pending, sigset_t *blocked);

void sigset_test_exit(void)
{
return;
}

#ifdef DEF_KERNEL
static int sigset_test_init()
#else
int main()
#endif
{
sigset_t cleaned;

cleaned = (sigset_t) { {0, 0} };
/* these are non-fatal signals. Other signals are if their action is SIG_DFL */
SIGADDSET(&cleaned, SIGCONT);
SIGADDSET(&cleaned, SIGCHLD);
SIGADDSET(&cleaned, SIGWINCH);
SIGADDSET(&cleaned, SIGURG);
SIGADDSET(&cleaned, SIGTSTP);
SIGADDSET(&cleaned, SIGTTIN);
SIGADDSET(&cleaned, SIGTTOU);
SIGADDSET(&cleaned, SIGSTOP);
ssi_fatal_sigset = (sigset_t) { {-1, -1} };

//uncomenting this line fixes the problem
//printk(KERN_INFO "sigset_test: fatal %p, stop %p\n", &ssi_fatal_sigset, &ssi_stop_set);

/* ssi_fatal_sigset is a mask of all signals that are fatal */
//commenting the line below fixes the problem
ssi_fatal_sigset = cleaned;

ssi_stop_set = (sigset_t) { {0, 0} };
printk(KERN_INFO "sigset_test after zeroing\n");
print_pending_signals(&ssi_stop_set, NULL);

SIGADDSET(&ssi_stop_set, SIGTSTP);
printk(KERN_INFO "sigset_test after %d\n", SIGTSTP);
print_pending_signals(&ssi_stop_set, NULL);

SIGADDSET(&ssi_stop_set, SIGTTIN);
printk(KERN_INFO "sigset_test after %d\n", SIGTTIN);
print_pending_signals(&ssi_stop_set, NULL);

SIGADDSET(&ssi_stop_set, SIGTTOU);
printk(KERN_INFO "sigset_test after %d\n", SIGTTOU);
print_pending_signals(&ssi_stop_set, NULL);

SIGADDSET(&ssi_stop_set, SIGSTOP);
printk(KERN_INFO "sigset_test after %d\n", SIGSTOP);
print_pending_signals(&ssi_stop_set, NULL);
return 1;
}

static void print_pending_signals(sigset_t *pending, sigset_t *blocked)
{
int i;

if(pending->sig[0] == 0 && pending->sig[1] == 0) {
printk(KERN_INFO "sigset_t: no set signals\n");
return;
}
if(blocked) {
for(i = 0; i < _NSIG; i++) {
if(SIGISMEMBER(pending, i+1)) {
printk(KERN_INFO "sigset_test: set signal %d is%sblocked\n", i+1, SIGISMEMBER(blocked, i+1) ? " " : " not ");
}
}
} else {
for(i = 0; i < _NSIG; i++) {
if(SIGISMEMBER(pending, i+1)) {
printk(KERN_INFO "sigset_test: set signal %d\n", i+1);
}
}
}
}


Attachments:
sigset_test.c (3.75 kB)

2005-11-17 07:17:05

by Constantine Gavrilov

[permalink] [raw]
Subject: gcc optimizer miscompiles code with sigaddset on i386 if sig arg is const -- PATCH proposed

--- signal.h.orig Thu Nov 17 08:47:14 2005
+++ signal.h Thu Nov 17 08:54:12 2005
@@ -186,16 +186,39 @@

#define __HAVE_ARCH_SIG_BITOPS

-static __inline__ void sigaddset(sigset_t *set, int _sig)
+#define sigaddset(set,sig) \
+ (__builtin_constant_p(sig) ? \
+ __const_sigaddset((set),(sig)) : \
+ __gen_sigaddset((set),(sig)))
+
+static __inline__ void __gen_sigaddset(sigset_t *set, int _sig)
{
__asm__("btsl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
}

-static __inline__ void sigdelset(sigset_t *set, int _sig)
+static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
+{
+ unsigned long sig = _sig - 1;
+ set->sig[sig / _NSIG_BPW] |= 1 << (sig % _NSIG_BPW);
+}
+
+#define sigdelset(set,sig) \
+ (__builtin_constant_p(sig) ? \
+ __const_sigdelset((set),(sig)) : \
+ __gen_sigdelset((set),(sig)))
+
+
+static __inline__ void __gen_sigdelset(sigset_t *set, int _sig)
{
__asm__("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
}

+static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
+{
+ unsigned long sig = _sig - 1;
+ set->sig[sig / _NSIG_BPW] &= ~(1 << (sig % _NSIG_BPW));
+}
+
static __inline__ int __const_sigismember(sigset_t *set, int _sig)
{
unsigned long sig = _sig - 1;


Attachments:
sigset_test.c (4.15 kB)
sigset_ops.patch (1.25 kB)
Download all attachments

2005-11-17 09:41:46

by Constantine Gavrilov

[permalink] [raw]
Subject: Re: gcc optimizer miscompiles code with sigaddset on i386 if sig arg is const -- PATCH proposed

--- signal.h.orig Thu Nov 17 08:47:14 2005
+++ signal.h Thu Nov 17 11:19:55 2005
@@ -186,14 +186,37 @@

#define __HAVE_ARCH_SIG_BITOPS

-static __inline__ void sigaddset(sigset_t *set, int _sig)
+#define sigaddset(set,sig) \
+ (__builtin_constant_p(sig) ? \
+ __const_sigaddset((set),(sig)) : \
+ __gen_sigaddset((set),(sig)))
+
+static __inline__ void __gen_sigaddset(sigset_t *set, int _sig)
+{
+ __asm__("btsl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
+}
+
+static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
+{
+ unsigned long sig = _sig - 1;
+ set->sig[sig / _NSIG_BPW] |= 1 << (sig % _NSIG_BPW);
+}
+
+#define sigdelset(set,sig) \
+ (__builtin_constant_p(sig) ? \
+ __const_sigdelset((set),(sig)) : \
+ __gen_sigdelset((set),(sig)))
+
+
+static __inline__ void __gen_sigdelset(sigset_t *set, int _sig)
{
- __asm__("btsl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
+ __asm__("btrl %1,%0" : "+m"(*set) : "Ir"(_sig - 1) : "cc");
}

-static __inline__ void sigdelset(sigset_t *set, int _sig)
+static __inline__ void __const_sigaddset(sigset_t *set, int _sig)
{
- __asm__("btrl %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
+ unsigned long sig = _sig - 1;
+ set->sig[sig / _NSIG_BPW] &= ~(1 << (sig % _NSIG_BPW));
}

static __inline__ int __const_sigismember(sigset_t *set, int _sig)


Attachments:
sigset_ops.patch (1.33 kB)