[Glibc-bsd-commits] r4167 - trunk/glibc-ports/kfreebsd/nptl

Robert Millan rmh at alioth.debian.org
Mon Apr 2 05:25:13 UTC 2012


Author: rmh
Date: 2012-04-02 05:25:13 +0000 (Mon, 02 Apr 2012)
New Revision: 4167

Modified:
   trunk/glibc-ports/kfreebsd/nptl/kernel-posix-timers.h
   trunk/glibc-ports/kfreebsd/nptl/timer_create.c
   trunk/glibc-ports/kfreebsd/nptl/timer_delete.c
   trunk/glibc-ports/kfreebsd/nptl/timer_getoverr.c
   trunk/glibc-ports/kfreebsd/nptl/timer_gettime.c
   trunk/glibc-ports/kfreebsd/nptl/timer_routines.c
   trunk/glibc-ports/kfreebsd/nptl/timer_settime.c
Log:

Misc portability fixes to make the imported code from NPTL work with kFreeBSD.

This is the first in a set of two commits to adapt code from NPTL/Linux to
LinuxThreads/kFreeBSD.  I've split it in two commits so that the intermediate
step can be reused later when NPTL is ported to kFreeBSD.



Modified: trunk/glibc-ports/kfreebsd/nptl/kernel-posix-timers.h
===================================================================
--- trunk/glibc-ports/kfreebsd/nptl/kernel-posix-timers.h	2012-04-02 05:21:55 UTC (rev 4166)
+++ trunk/glibc-ports/kfreebsd/nptl/kernel-posix-timers.h	2012-04-02 05:25:13 UTC (rev 4167)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2007, 2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper at redhat.com>, 2003.
 
@@ -21,6 +21,7 @@
 #include <setjmp.h>
 #include <signal.h>
 #include <sys/types.h>
+#include <sys/_types.h>
 
 
 /* Nonzero if the system calls are not available.  */
@@ -33,7 +34,7 @@
 extern pthread_once_t __helper_once attribute_hidden;
 
 /* TID of the helper thread.  */
-extern pid_t __helper_tid attribute_hidden;
+extern __lwpid_t __helper_tid attribute_hidden;
 
 /* List of active SIGEV_THREAD timers.  */
 extern struct timer *__active_timer_sigev_thread attribute_hidden;
@@ -66,3 +67,53 @@
   /* Next element in list of active SIGEV_THREAD timers.  */
   struct timer *next;
 };
+
+extern struct timer *__all_timers[TIMER_MAX];
+
+static inline struct timer *
+__kfreebsd_timer_alloc ()
+{
+  unsigned int i;
+  struct timer *timer = malloc (sizeof (struct timer));
+
+  /* Find a free slot (and reserve it atomically).  */
+  for (i = 0; i < TIMER_MAX; i++)
+    if (atomic_compare_and_exchange_val_acq (&__all_timers[i],
+					     timer, NULL) == NULL)
+      return timer;
+
+  errno = EAGAIN;
+  return NULL;
+}
+
+static inline struct timer *
+__kfreebsd_timer_id2ptr (timer_t id)
+{
+  void *ret = NULL;
+
+  if (id >= 0 && id < TIMER_MAX)
+    ret = __all_timers[id];
+
+  if (! ret)
+    errno = EINVAL;
+
+  return ret;
+}
+
+static inline timer_t
+__kfreebsd_timer_ptr2id (struct timer *ptr)
+{
+  unsigned int i;
+  for (i = 0; i < TIMER_MAX; i++)
+    if (__all_timers[i] == ptr)
+      return i;
+
+  return -1;
+}
+
+void static inline
+__kfreebsd_timer_free (struct timer *ptr)
+{
+  __all_timers[__kfreebsd_timer_ptr2id (ptr)] = NULL;
+  free (ptr);
+}

Modified: trunk/glibc-ports/kfreebsd/nptl/timer_create.c
===================================================================
--- trunk/glibc-ports/kfreebsd/nptl/timer_create.c	2012-04-02 05:21:55 UTC (rev 4166)
+++ trunk/glibc-ports/kfreebsd/nptl/timer_create.c	2012-04-02 05:25:13 UTC (rev 4167)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003,2004, 2007, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2003,2004, 2007, 2009, 2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper at redhat.com>, 2003.
 
@@ -31,7 +31,7 @@
 #include "kernel-posix-cpu-timers.h"
 
 
-#ifdef __NR_timer_create
+#ifdef SYS_ktimer_create
 # ifndef __ASSUME_POSIX_TIMERS
 static int compat_timer_create (clockid_t clock_id, struct sigevent *evp,
 				timer_t *timerid);
@@ -59,12 +59,6 @@
   if  (__no_posix_timers >= 0)
 # endif
     {
-      clockid_t syscall_clockid = (clock_id == CLOCK_PROCESS_CPUTIME_ID
-				   ? MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED)
-				   : clock_id == CLOCK_THREAD_CPUTIME_ID
-				   ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
-				   : clock_id);
-
       /* If the user wants notification via a thread we need to handle
 	 this special.  */
       if (evp == NULL
@@ -72,12 +66,8 @@
 	{
 	  struct sigevent local_evp;
 
-	  /* We avoid allocating too much memory by basically
-	     using struct timer as a derived class with the
-	     first two elements being in the superclass.  We only
-	     need these two elements here.  */
-	  struct timer *newp = (struct timer *) malloc (offsetof (struct timer,
-								  thrfunc));
+	  struct timer *newp = __kfreebsd_timer_alloc ();
+
 	  if (newp == NULL)
 	    /* No more memory.  */
 	    return -1;
@@ -95,7 +85,7 @@
 	    }
 
 	  kernel_timer_t ktimerid;
-	  int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp,
+	  int retval = INLINE_SYSCALL (ktimer_create, 3, clock_id, evp,
 				       &ktimerid);
 
 # ifndef __ASSUME_POSIX_TIMERS
@@ -112,19 +102,19 @@
 					? evp->sigev_notify : SIGEV_SIGNAL);
 		  newp->ktimerid = ktimerid;
 
-		  *timerid = (timer_t) newp;
+		  *timerid = __kfreebsd_timer_ptr2id (newp);
 		}
 	      else
 		{
 		  /* Cannot allocate the timer, fail.  */
-		  free (newp);
+		  __kfreebsd_timer_free (newp);
 		  retval = -1;
 		}
 
 	      return retval;
 	    }
 
-	  free (newp);
+	  __kfreebsd_timer_free (newp);
 
 # ifndef __ASSUME_POSIX_TIMERS
 	  /* When we come here the syscall does not exist.  Make sure we
@@ -138,13 +128,11 @@
 	  /* Make sure we have the necessary kernel support.  */
 	  if (__no_posix_timers == 0)
 	    {
-	      INTERNAL_SYSCALL_DECL (err);
 	      struct timespec ts;
 	      int res;
-	      res = INTERNAL_SYSCALL (clock_getres, err, 2,
-				      CLOCK_REALTIME, &ts);
-	      __no_posix_timers = (INTERNAL_SYSCALL_ERROR_P (res, err)
-				   ? -1 : 1);
+	      res = INLINE_SYSCALL (clock_getres, 2,
+				    CLOCK_REALTIME, &ts);
+	      __no_posix_timers = (res == -1 ? -1 : 1);
 	    }
 
 	  if (__no_posix_timers > 0)
@@ -160,7 +148,7 @@
 		}
 
 	      struct timer *newp;
-	      newp = (struct timer *) malloc (sizeof (struct timer));
+	      newp = __kfreebsd_timer_alloc ();
 	      if (newp == NULL)
 		return -1;
 
@@ -197,15 +185,15 @@
 	      struct sigevent sev =
 		{ .sigev_value.sival_ptr = newp,
 		  .sigev_signo = SIGTIMER,
-		  .sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID,
-		  ._sigev_un = { ._pad = { [0] = __helper_tid } } };
+		  .sigev_notify = SIGEV_THREAD_ID,
+		  .sigev_notify_thread_id = __helper_tid,
+		};
 
 	      /* Create the timer.  */
-	      INTERNAL_SYSCALL_DECL (err);
 	      int res;
-	      res = INTERNAL_SYSCALL (timer_create, err, 3,
-				      syscall_clockid, &sev, &newp->ktimerid);
-	      if (! INTERNAL_SYSCALL_ERROR_P (res, err))
+	      res = INLINE_SYSCALL (ktimer_create, 3,
+				      clock_id, &sev, &newp->ktimerid);
+	      if (res != -1)
 		{
 		  /* Add to the queue of active timers with thread
 		     delivery.  */
@@ -214,15 +202,13 @@
 		  __active_timer_sigev_thread = newp;
 		  pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
 
-		  *timerid = (timer_t) newp;
+		  *timerid = __kfreebsd_timer_ptr2id (newp);
 		  return 0;
 		}
 
 	      /* Free the resources.  */
-	      free (newp);
+	      __kfreebsd_timer_free (newp);
 
-	      __set_errno (INTERNAL_SYSCALL_ERRNO (res, err));
-
 	      return -1;
 	    }
 	}

Modified: trunk/glibc-ports/kfreebsd/nptl/timer_delete.c
===================================================================
--- trunk/glibc-ports/kfreebsd/nptl/timer_delete.c	2012-04-02 05:21:55 UTC (rev 4166)
+++ trunk/glibc-ports/kfreebsd/nptl/timer_delete.c	2012-04-02 05:25:13 UTC (rev 4167)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2007, 2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper at redhat.com>, 2003.
 
@@ -25,7 +25,7 @@
 #include "kernel-posix-timers.h"
 
 
-#ifdef __NR_timer_delete
+#ifdef SYS_ktimer_delete
 # ifndef __ASSUME_POSIX_TIMERS
 static int compat_timer_delete (timer_t timerid);
 #  define timer_delete static compat_timer_delete
@@ -47,10 +47,12 @@
   if (__no_posix_timers >= 0)
 # endif
     {
-      struct timer *kt = (struct timer *) timerid;
+      struct timer *kt = __kfreebsd_timer_id2ptr (timerid);
+      if (! kt)
+	return -1;
 
       /* Delete the kernel timer object.  */
-      int res = INLINE_SYSCALL (timer_delete, 1, kt->ktimerid);
+      int res = INLINE_SYSCALL (ktimer_delete, 1, kt->ktimerid);
 
       if (res == 0)
 	{
@@ -81,7 +83,7 @@
 # endif
 
 	  /* Free the memory.  */
-	  (void) free (kt);
+	  (void) __kfreebsd_timer_free (kt);
 
 	  return 0;
 	}

Modified: trunk/glibc-ports/kfreebsd/nptl/timer_getoverr.c
===================================================================
--- trunk/glibc-ports/kfreebsd/nptl/timer_getoverr.c	2012-04-02 05:21:55 UTC (rev 4166)
+++ trunk/glibc-ports/kfreebsd/nptl/timer_getoverr.c	2012-04-02 05:25:13 UTC (rev 4167)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper at redhat.com>, 2003.
 
@@ -24,7 +24,7 @@
 #include "kernel-posix-timers.h"
 
 
-#ifdef __NR_timer_getoverrun
+#ifdef SYS_ktimer_getoverrun
 # ifndef __ASSUME_POSIX_TIMERS
 static int compat_timer_getoverrun (timer_t timerid);
 #  define timer_getoverrun static compat_timer_getoverrun
@@ -46,10 +46,12 @@
   if (__no_posix_timers >= 0)
 # endif
     {
-      struct timer *kt = (struct timer *) timerid;
+      struct timer *kt = __kfreebsd_timer_id2ptr (timerid);
+      if (! kt)
+	return -1;
 
       /* Get the information from the kernel.  */
-      int res = INLINE_SYSCALL (timer_getoverrun, 1, kt->ktimerid);
+      int res = INLINE_SYSCALL (ktimer_getoverrun, 1, kt->ktimerid);
 
 # ifndef __ASSUME_POSIX_TIMERS
       if (res != -1 || errno != ENOSYS)

Modified: trunk/glibc-ports/kfreebsd/nptl/timer_gettime.c
===================================================================
--- trunk/glibc-ports/kfreebsd/nptl/timer_gettime.c	2012-04-02 05:21:55 UTC (rev 4166)
+++ trunk/glibc-ports/kfreebsd/nptl/timer_gettime.c	2012-04-02 05:25:13 UTC (rev 4167)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper at redhat.com>, 2003.
 
@@ -25,7 +25,7 @@
 #include "kernel-posix-timers.h"
 
 
-#ifdef __NR_timer_gettime
+#ifdef SYS_ktimer_gettime
 # ifndef __ASSUME_POSIX_TIMERS
 static int compat_timer_gettime (timer_t timerid, struct itimerspec *value);
 #  define timer_gettime static compat_timer_gettime
@@ -48,10 +48,12 @@
   if (__no_posix_timers >= 0)
 # endif
     {
-      struct timer *kt = (struct timer *) timerid;
+      struct timer *kt = __kfreebsd_timer_id2ptr (timerid);
+      if (! kt)
+	return -1;
 
       /* Delete the kernel timer object.  */
-      int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value);
+      int res = INLINE_SYSCALL (ktimer_gettime, 2, kt->ktimerid, value);
 
 # ifndef __ASSUME_POSIX_TIMERS
       if (res != -1 || errno != ENOSYS)

Modified: trunk/glibc-ports/kfreebsd/nptl/timer_routines.c
===================================================================
--- trunk/glibc-ports/kfreebsd/nptl/timer_routines.c	2012-04-02 05:21:55 UTC (rev 4166)
+++ trunk/glibc-ports/kfreebsd/nptl/timer_routines.c	2012-04-02 05:25:13 UTC (rev 4167)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper at redhat.com>, 2003.
 
@@ -22,10 +22,16 @@
 #include <signal.h>
 #include <stdbool.h>
 #include <sysdep.h>
+#include <sys/_types.h> /* __lwpid_t */
+#include <atomic.h>
 #include <kernel-features.h>
 #include <nptl/pthreadP.h>
 #include "kernel-posix-timers.h"
 
+/* NPTL/Linux simply casts "timer_t" to "struct timer *", but on
+   kFreeBSD timer_t may not be large enough to hold a pointer.
+   So we store the pointers here... (sigh) */
+struct timer *__all_timers[TIMER_MAX];
 
 /* List of active SIGEV_THREAD timers.  */
 struct timer *__active_timer_sigev_thread;
@@ -40,7 +46,7 @@
 };
 
 
-#ifdef __NR_timer_create
+#ifdef SYS_ktimer_create
 /* Helper thread to call the user-provided function.  */
 static void *
 timer_sigev_thread (void *arg)
@@ -50,8 +56,7 @@
      signals.  */
   sigset_t ss;
   sigemptyset (&ss);
-  INTERNAL_SYSCALL_DECL (err);
-  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8);
+  sigprocmask (SIG_SETMASK, &ss, NULL);
 
   struct thread_start_data *td = (struct thread_start_data *) arg;
 
@@ -91,8 +96,7 @@
 
       /* 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, &ss, &si, NULL,
-				   _NSIG / 8);
+      int result = sigtimedwait (&ss, &si, NULL);
 
       LIBC_CANCEL_RESET (oldtype);
 
@@ -100,7 +104,7 @@
 	{
 	  if (si.si_code == SI_TIMER)
 	    {
-	      struct timer *tk = (struct timer *) si.si_ptr;
+	      struct timer *tk = (struct timer *) si.si_value.sival_ptr;
 
 	      /* Check the timer is still used and will not go away
 		 while we are reading the values here.  */
@@ -132,7 +136,9 @@
 
 	      pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
 	    }
-	  else if (si.si_code == SI_TKILL)
+	  else if (si.si_code == SI_LWP
+		   /* Backward compatibility (see rev 211732 in -CURRENT).  */
+		   || si.si_code == SI_USER)
 	    /* The thread is canceled.  */
 	    pthread_exit (NULL);
 	}
@@ -145,7 +151,7 @@
 
 
 /* TID of the helper thread.  */
-pid_t __helper_tid attribute_hidden;
+__lwpid_t __helper_tid attribute_hidden;
 
 
 /* Reset variables so that after a fork a new helper thread gets started.  */
@@ -176,8 +182,7 @@
   sigset_t oss;
   sigfillset (&ss);
   __sigaddset (&ss, SIGCANCEL);
-  INTERNAL_SYSCALL_DECL (err);
-  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8);
+  sigprocmask (SIG_SETMASK, &ss, &oss);
 
   /* Create the helper thread for this timer.  */
   pthread_t th;
@@ -187,8 +192,7 @@
     __helper_tid = ((struct pthread *) th)->tid;
 
   /* Restore the signal mask.  */
-  INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL,
-		    _NSIG / 8);
+  sigprocmask (SIG_SETMASK, &oss, NULL);
 
   /* No need for the attribute anymore.  */
   (void) pthread_attr_destroy (&attr);

Modified: trunk/glibc-ports/kfreebsd/nptl/timer_settime.c
===================================================================
--- trunk/glibc-ports/kfreebsd/nptl/timer_settime.c	2012-04-02 05:21:55 UTC (rev 4166)
+++ trunk/glibc-ports/kfreebsd/nptl/timer_settime.c	2012-04-02 05:25:13 UTC (rev 4167)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper at redhat.com>, 2003.
 
@@ -25,7 +25,7 @@
 #include "kernel-posix-timers.h"
 
 
-#ifdef __NR_timer_settime
+#ifdef SYS_ktimer_settime
 # ifndef __ASSUME_POSIX_TIMERS
 static int compat_timer_settime (timer_t timerid, int flags,
 				 const struct itimerspec *value,
@@ -52,10 +52,12 @@
   if (__no_posix_timers >= 0)
 # endif
     {
-      struct timer *kt = (struct timer *) timerid;
+      struct timer *kt = __kfreebsd_timer_id2ptr (timerid);
+      if (! kt)
+	return -1;
 
       /* Delete the kernel timer object.  */
-      int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
+      int res = INLINE_SYSCALL (ktimer_settime, 4, kt->ktimerid, flags,
 				value, ovalue);
 
 # ifndef __ASSUME_POSIX_TIMERS




More information about the Glibc-bsd-commits mailing list