svn commit: branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux

sjhill at uclibc.org sjhill at uclibc.org
Thu Dec 8 05:06:42 UTC 2005


Author: sjhill
Date: 2005-12-07 21:06:40 -0800 (Wed, 07 Dec 2005)
New Revision: 12722

Log:
Bring in new functions for NPTL. These are actually from glibc out of
the 'sysdeps/unix/sysv/linux' directory, but including the 'pthreadP.h'
header to activate NPTL-specific code.


Modified:
   branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c
   branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c
   branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c
   branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c


Changeset:
Modified: branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c
===================================================================
--- branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c	2005-12-08 05:02:08 UTC (rev 12721)
+++ branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c	2005-12-08 05:06:40 UTC (rev 12722)
@@ -1,2 +1,88 @@
-#include <nptl/pthreadP.h>
-#include "../../../../../sysdeps/unix/sysv/linux/sigtimedwait.c"
+/* Copyright (C) 1997,1998,2000,2002,2003,2004 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthreadP.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+
+#ifdef __NR_rt_sigtimedwait
+
+static int
+do_sigtimedwait (const sigset_t *set, siginfo_t *info,
+		 const struct timespec *timeout)
+{
+#ifdef SIGCANCEL
+  sigset_t tmpset;
+  if (set != NULL
+      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
+# ifdef SIGSETXID
+	  || __builtin_expect (__sigismember (set, SIGSETXID), 0)
+# endif
+	  ))
+    {
+      /* Create a temporary mask without the bit for SIGCANCEL set.  */
+      // We are not copying more than we have to.
+      memcpy (&tmpset, set, _NSIG / 8);
+      __sigdelset (&tmpset, SIGCANCEL);
+# ifdef SIGSETXID
+      __sigdelset (&tmpset, SIGSETXID);
+# endif
+      set = &tmpset;
+    }
+#endif
+
+    /* XXX The size argument hopefully will have to be changed to the
+       real size of the user-level sigset_t.  */
+  int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set,
+			       info, timeout, _NSIG / 8);
+
+  /* The kernel generates a SI_TKILL code in si_code in case tkill is
+     used.  tkill is transparently used in raise().  Since having
+     SI_TKILL as a code is useful in general we fold the results
+     here.  */
+  if (result != -1 && info != NULL && info->si_code == SI_TKILL)
+    info->si_code = SI_USER;
+
+  return result;
+}
+
+
+/* Return any pending signal or wait for one for the given time.  */
+int attribute_hidden
+__sigtimedwait (const sigset_t *set, siginfo_t *info,
+		const struct timespec *timeout)
+{
+  if (SINGLE_THREAD_P)
+    return do_sigtimedwait (set, info, timeout);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  /* XXX The size argument hopefully will have to be changed to the
+     real size of the user-level sigset_t.  */
+  int result = do_sigtimedwait (set, info, timeout);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+weak_alias (__sigtimedwait, sigtimedwait)
+#endif

Modified: branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c
===================================================================
--- branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c	2005-12-08 05:02:08 UTC (rev 12721)
+++ branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c	2005-12-08 05:06:40 UTC (rev 12722)
@@ -1,2 +1,105 @@
-#include <nptl/pthreadP.h>
-#include "../../../../../sysdeps/unix/sysv/linux/sigwait.c"
+/* Copyright (C) 1997,1998,2000,2002-2004,2005 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthreadP.h>
+#include <errno.h>
+#include <signal.h>
+#define __need_NULL
+#include <stddef.h>
+#include <string.h>
+
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+
+#ifdef __NR_rt_sigtimedwait
+
+/* Return any pending signal or wait for one for the given time.  */
+static int
+do_sigwait (const sigset_t *set, int *sig)
+{
+  int ret;
+
+#ifdef SIGCANCEL
+  sigset_t tmpset;
+  if (set != NULL
+      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
+# ifdef SIGSETXID
+	  || __builtin_expect (__sigismember (set, SIGSETXID), 0)
+# endif
+	  ))
+    {
+      /* Create a temporary mask without the bit for SIGCANCEL set.  */
+      // We are not copying more than we have to.
+      memcpy (&tmpset, set, _NSIG / 8);
+      __sigdelset (&tmpset, SIGCANCEL);
+# ifdef SIGSETXID
+      __sigdelset (&tmpset, SIGSETXID);
+# endif
+      set = &tmpset;
+    }
+#endif
+
+  /* XXX The size argument hopefully will have to be changed to the
+     real size of the user-level sigset_t.  */
+#ifdef INTERNAL_SYSCALL
+  INTERNAL_SYSCALL_DECL (err);
+  do
+    ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, set,
+			    NULL, NULL, _NSIG / 8);
+  while (INTERNAL_SYSCALL_ERROR_P (ret, err)
+	 && INTERNAL_SYSCALL_ERRNO (ret, err) == EINTR);
+  if (! INTERNAL_SYSCALL_ERROR_P (ret, err))
+    {
+      *sig = ret;
+      ret = 0;
+    }
+  else
+    ret = INTERNAL_SYSCALL_ERRNO (ret, err);
+#else
+  do
+    ret = INLINE_SYSCALL (rt_sigtimedwait, 4, set,
+			  NULL, NULL, _NSIG / 8);
+  while (ret == -1 && errno == EINTR);
+  if (ret != -1)
+    {
+      *sig = ret;
+      ret = 0;
+    }
+  else
+    ret = errno;
+#endif
+
+  return ret;
+}
+
+int attribute_hidden
+__sigwait (const sigset_t *set, int *sig)
+{
+  if (SINGLE_THREAD_P)
+    return do_sigwait (set, sig);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = do_sigwait (set, sig);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+weak_alias (__sigwait, sigwait)
+#endif

Modified: branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c
===================================================================
--- branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c	2005-12-08 05:02:08 UTC (rev 12721)
+++ branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c	2005-12-08 05:06:40 UTC (rev 12722)
@@ -1,2 +1,88 @@
-#include <nptl/pthreadP.h>
-#include "../../../../../sysdeps/unix/sysv/linux/sigwaitinfo.c"
+/* Copyright (C) 1997,1998,2000,2002,2003,2004 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
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthreadP.h>
+#include <errno.h>
+#include <signal.h>
+#define __need_NULL
+#include <stddef.h>
+#include <string.h>
+
+#include <sysdep-cancel.h>
+#include <sys/syscall.h>
+
+#ifdef __NR_rt_sigtimedwait
+
+static int
+do_sigwaitinfo (const sigset_t *set, siginfo_t *info)
+{
+#ifdef SIGCANCEL
+  sigset_t tmpset;
+  if (set != NULL
+      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
+# ifdef SIGSETXID
+	  || __builtin_expect (__sigismember (set, SIGSETXID), 0)
+# endif
+	  ))
+    {
+      /* Create a temporary mask without the bit for SIGCANCEL set.  */
+      // We are not copying more than we have to.
+      memcpy (&tmpset, set, _NSIG / 8);
+      __sigdelset (&tmpset, SIGCANCEL);
+# ifdef SIGSETXID
+      __sigdelset (&tmpset, SIGSETXID);
+# endif
+      set = &tmpset;
+    }
+#endif
+
+  /* XXX The size argument hopefully will have to be changed to the
+     real size of the user-level sigset_t.  */
+  int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set,
+			       info, NULL, _NSIG / 8);
+
+  /* The kernel generates a SI_TKILL code in si_code in case tkill is
+     used.  tkill is transparently used in raise().  Since having
+     SI_TKILL as a code is useful in general we fold the results
+     here.  */
+  if (result != -1 && info != NULL && info->si_code == SI_TKILL)
+    info->si_code = SI_USER;
+
+  return result;
+}
+
+
+/* Return any pending signal or wait for one for the given time.  */
+int attribute_hidden
+__sigwaitinfo (const sigset_t *set, siginfo_t *info)
+{
+  if (SINGLE_THREAD_P)
+    return do_sigwaitinfo (set, info);
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  /* XXX The size argument hopefully will have to be changed to the
+     real size of the user-level sigset_t.  */
+  int result = do_sigwaitinfo (set, info);
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+weak_alias (__sigwaitinfo, sigwaitinfo)
+#endif

Modified: branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c
===================================================================
--- branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c	2005-12-08 05:02:08 UTC (rev 12721)
+++ branches/uClibc-nptl/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c	2005-12-08 05:06:40 UTC (rev 12722)
@@ -1,2 +1,150 @@
-#include <nptl/pthreadP.h>
-#include <sysdeps/unix/sysv/linux/sleep.c>
+/* Implementation of the POSIX sleep function using nanosleep.
+   Copyright (C) 1996,1997,1998,1999,2003,2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper at cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <pthreadP.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>	/* For the real memset prototype.  */
+#include <unistd.h>
+#include <sys/param.h>
+
+
+#if 0
+static void
+cl (void *arg)
+{
+  (void) __sigprocmask (SIG_SETMASK, arg, (sigset_t *) NULL);
+}
+#endif
+
+
+/* We are going to use the `nanosleep' syscall of the kernel.  But the
+   kernel does not implement the stupid SysV SIGCHLD vs. SIG_IGN
+   behaviour for this syscall.  Therefore we have to emulate it here.  */
+unsigned int
+__sleep (unsigned int seconds)
+{
+  const unsigned int max
+    = (unsigned int) (((unsigned long int) (~((time_t) 0))) >> 1);
+  struct timespec ts;
+  sigset_t set, oset;
+  unsigned int result;
+
+  /* This is not necessary but some buggy programs depend on this.  */
+  if (__builtin_expect (seconds == 0, 0))
+    {
+#ifdef CANCELLATION_P
+      CANCELLATION_P (THREAD_SELF);
+#endif
+      return 0;
+    }
+
+  ts.tv_sec = 0;
+  ts.tv_nsec = 0;
+ again:
+  if (sizeof (ts.tv_sec) <= sizeof (seconds))
+    {
+      /* Since SECONDS is unsigned assigning the value to .tv_sec can
+	 overflow it.  In this case we have to wait in steps.  */
+      ts.tv_sec += MIN (seconds, max);
+      seconds -= (unsigned int) ts.tv_sec;
+    }
+  else
+    {
+      ts.tv_sec = (time_t) seconds;
+      seconds = 0;
+    }
+
+  /* Linux will wake up the system call, nanosleep, when SIGCHLD
+     arrives even if SIGCHLD is ignored.  We have to deal with it
+     in libc.  We block SIGCHLD first.  */
+  __sigemptyset (&set);
+  __sigaddset (&set, SIGCHLD);
+  if (__sigprocmask (SIG_BLOCK, &set, &oset))
+    return -1;
+
+  /* If SIGCHLD is already blocked, we don't have to do anything.  */
+  if (!__sigismember (&oset, SIGCHLD))
+    {
+      int saved_errno;
+      struct sigaction oact;
+
+      __sigemptyset (&set);
+      __sigaddset (&set, SIGCHLD);
+
+      /* We get the signal handler for SIGCHLD.  */
+      if (sigaction (SIGCHLD, (struct sigaction *) NULL, &oact) < 0)
+	{
+	  saved_errno = errno;
+	  /* Restore the original signal mask.  */
+	  (void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
+	  __set_errno (saved_errno);
+	  return -1;
+	}
+
+      /* Note the sleep() is a cancellation point.  But since we call
+	 nanosleep() which itself is a cancellation point we do not
+	 have to do anything here.  */
+      if (oact.sa_handler == SIG_IGN)
+	{
+	  //__libc_cleanup_push (cl, &oset);
+
+	  /* We should leave SIGCHLD blocked.  */
+	  while (1)
+	    {
+	      result = nanosleep (&ts, &ts);
+
+	      if (result != 0 || seconds == 0)
+		break;
+
+	      if (sizeof (ts.tv_sec) <= sizeof (seconds))
+		{
+		  ts.tv_sec = MIN (seconds, max);
+		  seconds -= (unsigned int) ts.tv_nsec;
+		}
+	    }
+
+	  //__libc_cleanup_pop (0);
+
+	  saved_errno = errno;
+	  /* Restore the original signal mask.  */
+	  (void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
+	  __set_errno (saved_errno);
+
+	  goto out;
+	}
+
+      /* We should unblock SIGCHLD.  Restore the original signal mask.  */
+      (void) __sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
+    }
+
+  result = nanosleep (&ts, &ts);
+  if (result == 0 && seconds != 0)
+    goto again;
+
+ out:
+  if (result != 0)
+    /* Round remaining time.  */
+    result = seconds + (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L);
+
+  return result;
+}
+weak_alias (__sleep, sleep)




More information about the uClibc-cvs mailing list