This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]