This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
FreeBSD port (20): conversion between sigmask and sigset_t
- From: Bruno Haible <bruno at clisp dot org>
- To: libc-alpha at sources dot redhat dot com
- Date: Thu, 11 Jul 2002 14:25:42 +0200 (CEST)
- Subject: FreeBSD port (20): conversion between sigmask and sigset_t
Hi,
The functions sigblock(), sigpause(), sigsetmask(), sigvec() need to
convert between old-style 32-bit signal masks and larger sigset_t.
In the functions sigblock(), sigpause(), sigsetmask(), the platforms
with small sigset_t are handled well, but for the others the code is
slow (32 loop iterations for what could be a single "mov").
In the function sigvec() an abstraction sigset_set_old_mask(),
sigset_set_old_mask() is used. I propose to use this approach for the
other 3 functions as well.
Here is a patch that
1) Makes sysdeps/generic/sigset-cvt-mask.h work on more platforms by
default. Up to now it works only on platforms with small sigset_t.
2) Makes sigblock(), sigpause(), sigsetmask() use these primitives.
3) Makes it possible for me to use specialized conversion routines
in the FreeBSD port, where sigset_t has 128 bit and each conversion
can be done in 4 "mov" instructions.
Note that the Linux, Solaris and AIX ports are not affected by change 1)
because they each have their own sigset-cvt-mask.h.
2002-07-06 Bruno Haible <bruno@clisp.org>
* sysdeps/generic/sigset-cvt-mask.h (sigset_set_old_mask,
sigset_get_old_mask): Make it work with larger sigset_t.
* sysdeps/posix/sigblock.c (__sigblock): Use sigset_set_old_mask,
sigset_get_old_mask.
* sysdeps/posix/sigsetmask.c (__sigsetmask): Likewise.
* sysdeps/posix/sigpause.c (__sigpause): Use sigset_set_old_mask.
diff -r -c3 glibc-20020627.bak/sysdeps/generic/sigset-cvt-mask.h glibc-20020627/sysdeps/generic/sigset-cvt-mask.h
--- glibc-20020627.bak/sysdeps/generic/sigset-cvt-mask.h Tue Jul 10 23:00:33 2001
+++ glibc-20020627/sysdeps/generic/sigset-cvt-mask.h Fri Jul 5 01:17:07 2002
@@ -1,6 +1,6 @@
/* Convert between lowlevel sigmask and libc representation of sigset_t.
Generic version.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Joe Keane <jgk@jgk.org>.
@@ -19,6 +19,45 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
-#define sigset_set_old_mask(set, mask) (*(set) = (unsigned long int) (mask))
+/* Convert between an old-style 32-bit signal mask and a POSIX sigset_t. */
-#define sigset_get_old_mask(set, mask) ((mask) = (unsigned int) *(set))
+/* Perform *SET = MASK. Unused bits of *SET are set to 0. Exit -1 from
+ the current function if an error occurs. */
+#define sigset_set_old_mask(set, mask) \
+ do { \
+ if (sizeof (__sigset_t) == sizeof (unsigned int)) \
+ *(set) = (unsigned int) (mask); \
+ else \
+ { \
+ __sigset_t *__set = (set); \
+ unsigned int __mask = (mask); \
+ register unsigned int __sig; \
+ \
+ if (__sigemptyset (__set) < 0) \
+ return -1; \
+ \
+ for (__sig = 1; __sig < NSIG && __sig <= sizeof (__mask) * 8; __sig++)\
+ if (__mask & sigmask (__sig)) \
+ if (__sigaddset (__set, __sig) < 0) \
+ return -1; \
+ } \
+ } while (0)
+
+/* Perform MASK = *SET. Unused bits of *SET are thrown away. */
+#define sigset_get_old_mask(set, mask) \
+ do { \
+ if (sizeof (__sigset_t) == sizeof (unsigned int)) \
+ (mask) = (unsigned int) *(set); \
+ else \
+ { \
+ __sigset_t *__set = (set); \
+ unsigned int __mask = 0; \
+ register unsigned int __sig; \
+ \
+ for (__sig = 1; __sig < NSIG && __sig <= sizeof (__mask) * 8; __sig++)\
+ if (__sigismember (__set, __sig)) \
+ mask |= sigmask (__sig); \
+ \
+ (mask) = __mask; \
+ } \
+ } while (0)
diff -r -c3 glibc-20020627.bak/sysdeps/posix/sigblock.c glibc-20020627/sysdeps/posix/sigblock.c
--- glibc-20020627.bak/sysdeps/posix/sigblock.c Tue Jul 10 23:01:08 2001
+++ glibc-20020627/sysdeps/posix/sigblock.c Fri Jul 5 01:17:10 2002
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 94, 95, 96, 97, 98, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1994-1998, 2001-2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -19,37 +19,21 @@
#include <errno.h>
#include <signal.h>
+#include "sigset-cvt-mask.h"
+
/* Block signals in MASK, returning the old mask. */
int
__sigblock (mask)
int mask;
{
- register unsigned int sig;
sigset_t set, oset;
- if (__sigemptyset (&set) < 0)
- return -1;
-
- if (sizeof (mask) == sizeof (set))
- *(int *) &set = mask;
- else if (sizeof (unsigned long int) == sizeof (set))
- *(unsigned long int *) &set = (unsigned int) mask;
- else
- for (sig = 1; sig < NSIG && sig <= sizeof (mask) * 8; ++sig)
- if ((mask & sigmask (sig)) && __sigaddset (&set, sig) < 0)
- return -1;
+ sigset_set_old_mask (&set, mask);
if (__sigprocmask (SIG_BLOCK, &set, &oset) < 0)
return -1;
- if (sizeof (mask) == sizeof (oset))
- mask = *(int *) &oset;
- else if (sizeof (unsigned long int) == sizeof (oset))
- mask = *(unsigned long int*) &oset;
- else
- for (sig = 1, mask = 0; sig < NSIG && sig <= sizeof (mask) * 8; ++sig)
- if (__sigismember (&oset, sig))
- mask |= sigmask (sig);
+ sigset_get_old_mask (&oset, mask);
return mask;
}
diff -r -c3 glibc-20020627.bak/sysdeps/posix/sigpause.c glibc-20020627/sysdeps/posix/sigpause.c
--- glibc-20020627.bak/sysdeps/posix/sigpause.c Tue Jul 10 23:01:08 2001
+++ glibc-20020627/sysdeps/posix/sigpause.c Fri Jul 5 01:17:10 2002
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 1994-1998, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 92, 1994-1998, 2000, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,13 +20,14 @@
#include <signal.h>
#include <stddef.h> /* For NULL. */
+#include "sigset-cvt-mask.h"
+
/* Set the mask of blocked signals to MASK,
wait for a signal to arrive, and then restore the mask. */
int
__sigpause (int sig_or_mask, int is_sig)
{
sigset_t set;
- int sig;
if (is_sig != 0)
{
@@ -38,17 +39,7 @@
}
else
{
- if (__sigemptyset (&set) < 0)
- return -1;
-
- if (sizeof (sig_or_mask) == sizeof (set))
- *(int *) &set = sig_or_mask;
- else if (sizeof (unsigned long int) == sizeof (set))
- *(unsigned long int *) &set = (unsigned int) sig_or_mask;
- else
- for (sig = 1; sig < NSIG; ++sig)
- if ((sig_or_mask & sigmask (sig)) && __sigaddset (&set, sig) < 0)
- return -1;
+ sigset_set_old_mask (&set, sig_or_mask);
}
return __sigsuspend (&set);
diff -r -c3 glibc-20020627.bak/sysdeps/posix/sigsetmask.c glibc-20020627/sysdeps/posix/sigsetmask.c
--- glibc-20020627.bak/sysdeps/posix/sigsetmask.c Tue Jul 10 23:01:08 2001
+++ glibc-20020627/sysdeps/posix/sigsetmask.c Fri Jul 5 01:17:10 2002
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,1994,1995,1996,1997,2001 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1994-1997,2001-2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -19,36 +19,20 @@
#include <errno.h>
#include <signal.h>
+#include "sigset-cvt-mask.h"
+
/* Set the mask of blocked signals to MASK, returning the old mask. */
int
__sigsetmask (int mask)
{
- register unsigned int sig;
sigset_t set, oset;
- if (__sigemptyset (&set) < 0)
- return -1;
-
- if (sizeof (mask) == sizeof (set))
- *(int *) &set = mask;
- else if (sizeof (unsigned long int) == sizeof (set))
- *(unsigned long int *) &set = (unsigned int) mask;
- else
- for (sig = 1; sig < NSIG && sig <= sizeof (mask) * 8; ++sig)
- if ((mask & sigmask (sig)) && __sigaddset (&set, sig) < 0)
- return -1;
+ sigset_set_old_mask (&set, mask);
if (__sigprocmask (SIG_SETMASK, &set, &oset) < 0)
return -1;
- if (sizeof (mask) == sizeof (oset))
- mask = *(int *) &oset;
- else if (sizeof (unsigned long int) == sizeof (oset))
- mask = *(unsigned long int *) &oset;
- else
- for (sig = 1, mask = 0; sig < NSIG && sig <= sizeof (mask) * 8; ++sig)
- if (__sigismember (&oset, sig))
- mask |= sigmask (sig);
+ sigset_get_old_mask (&oset, mask);
return mask;
}