[7/7] Cleanup timer_* routines

Message ID 20191210183221.26912-7-adhemerval.zanella@linaro.org
State New
Headers show
Series
  • [v3,1/7] Fix __libc_signal_block_all on sparc64
Related show

Commit Message

Adhemerval Zanella Dec. 10, 2019, 6:32 p.m.
- Two function are added that manipulate the list of active
    timers, __{add,remove}_active_timer_sigev.   This allows make
    both __active_timer_sigev_thread and
    __active_timer_sigev_thread_lock internal on timer_routine
    implementation.

  - Remove ununsed __no_posix_timers defition.

  - Use INLINE_SYSCALL_CALL on timer_* functions.

  - Simplify some code on timer_create and timer_routines, such as
    thread attribute handling and invalid notification method.

Checked on x86_64-linux-gnu and i686-linux-gnu.
---
 sysdeps/unix/sysv/linux/kernel-posix-timers.h |  13 +-
 sysdeps/unix/sysv/linux/timer_create.c        | 116 +++++++-----------
 sysdeps/unix/sysv/linux/timer_delete.c        |  42 ++-----
 sysdeps/unix/sysv/linux/timer_getoverr.c      |   2 +-
 sysdeps/unix/sysv/linux/timer_routines.c      |  50 ++++++--
 5 files changed, 100 insertions(+), 123 deletions(-)

-- 
2.17.1

Patch

diff --git a/sysdeps/unix/sysv/linux/kernel-posix-timers.h b/sysdeps/unix/sysv/linux/kernel-posix-timers.h
index d60cb95f80..bf17d8c915 100644
--- a/sysdeps/unix/sysv/linux/kernel-posix-timers.h
+++ b/sysdeps/unix/sysv/linux/kernel-posix-timers.h
@@ -21,10 +21,6 @@ 
 #include <signal.h>
 #include <sys/types.h>
 
-
-/* Nonzero if the system calls are not available.  */
-extern int __no_posix_timers attribute_hidden;
-
 /* Callback to start helper thread.  */
 extern void __start_helper_thread (void) attribute_hidden;
 
@@ -34,12 +30,6 @@  extern pthread_once_t __helper_once attribute_hidden;
 /* TID of the helper thread.  */
 extern pid_t __helper_tid attribute_hidden;
 
-/* List of active SIGEV_THREAD timers.  */
-extern struct timer *__active_timer_sigev_thread attribute_hidden;
-/* Lock for the __active_timer_sigev_thread.  */
-extern pthread_mutex_t __active_timer_sigev_thread_lock attribute_hidden;
-
-
 /* Type of timers in the kernel.  */
 typedef int kernel_timer_t;
 
@@ -64,3 +54,6 @@  struct timer
   /* Next element in list of active SIGEV_THREAD timers.  */
   struct timer *next;
 };
+
+void __add_active_timer_sigev (struct timer *tk) attribute_hidden;
+void __remove_active_timer_sigev (struct timer *tk) attribute_hidden;
diff --git a/sysdeps/unix/sysv/linux/timer_create.c b/sysdeps/unix/sysv/linux/timer_create.c
index 4e41ca011f..e5dcdaab65 100644
--- a/sysdeps/unix/sysv/linux/timer_create.c
+++ b/sysdeps/unix/sysv/linux/timer_create.c
@@ -16,17 +16,12 @@ 
    License along with the GNU C Library; see the file COPYING.LIB.  If
    not, see <https://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <pthread.h>
 #include <signal.h>
-#include <stdlib.h>
-#include <string.h>
 #include <time.h>
-#include <sysdep.h>
-#include <internaltypes.h>
-#include <nptl/pthreadP.h>
-#include "kernel-posix-timers.h"
-#include "kernel-posix-cpu-timers.h"
+
+#include <kernel-posix-timers.h>
+#include <kernel-posix-cpu-timers.h>
+#include <internal-signals.h>
 
 
 #ifdef timer_create_alias
@@ -38,17 +33,16 @@  int
 timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
 {
 #undef timer_create
-  {
-    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
-	|| __builtin_expect (evp->sigev_notify != SIGEV_THREAD, 1))
+  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);
+
+  switch (evp != NULL ? evp->sigev_notify : SIGEV_SIGNAL)
+    {
+    case SIGEV_NONE:
+    case SIGEV_SIGNAL:
       {
 	struct sigevent local_evp;
 
@@ -75,27 +69,22 @@  timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
 	  }
 
 	kernel_timer_t ktimerid;
-	int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp,
-				     &ktimerid);
-
-	if (retval != -1)
-	  {
-	    newp->sigev_notify = (evp != NULL
-				  ? evp->sigev_notify : SIGEV_SIGNAL);
-	    newp->ktimerid = ktimerid;
-
-	    *timerid = (timer_t) newp;
-	  }
-	else
+	int retval = INLINE_SYSCALL_CALL (timer_create, syscall_clockid, evp,
+					  &ktimerid);
+	if (retval != 0)
 	  {
 	    /* Cannot allocate the timer, fail.  */
 	    free (newp);
-	    retval = -1;
+	    return-1;
 	  }
 
-	return retval;
+	newp->sigev_notify = (evp != NULL ? evp->sigev_notify : SIGEV_SIGNAL);
+	newp->ktimerid = ktimerid;
+	*timerid = (timer_t) newp;
       }
-    else
+      break;
+
+   case SIGEV_THREAD:
       {
 	/* Create the helper thread.  */
 	pthread_once (&__helper_once, __start_helper_thread);
@@ -116,25 +105,10 @@  timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
 	newp->thrfunc = evp->sigev_notify_function;
 	newp->sigev_notify = SIGEV_THREAD;
 
-	/* We cannot simply copy the thread attributes since the
-	   implementation might keep internal information for
-	   each instance.  */
-	(void) pthread_attr_init (&newp->attr);
 	if (evp->sigev_notify_attributes != NULL)
-	  {
-	    struct pthread_attr *nattr;
-	    struct pthread_attr *oattr;
-
-	    nattr = (struct pthread_attr *) &newp->attr;
-	    oattr = (struct pthread_attr *) evp->sigev_notify_attributes;
-
-	    nattr->schedparam = oattr->schedparam;
-	    nattr->schedpolicy = oattr->schedpolicy;
-	    nattr->flags = oattr->flags;
-	    nattr->guardsize = oattr->guardsize;
-	    nattr->stackaddr = oattr->stackaddr;
-	    nattr->stacksize = oattr->stacksize;
-	  }
+	  newp->attr = *evp->sigev_notify_attributes;
+	else
+	  pthread_attr_init (&newp->attr);
 
 	/* In any case set the detach flag.  */
 	(void) pthread_attr_setdetachstate (&newp->attr,
@@ -148,29 +122,25 @@  timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
 	    ._sigev_un = { ._pad = { [0] = __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))
+	int res = INLINE_SYSCALL_CALL (timer_create, syscall_clockid, &sev,
+				       &newp->ktimerid);
+	if (res != 0)
 	  {
-	    /* Add to the queue of active timers with thread
-	       delivery.  */
-	    pthread_mutex_lock (&__active_timer_sigev_thread_lock);
-	    newp->next = __active_timer_sigev_thread;
-	    __active_timer_sigev_thread = newp;
-	    pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
-
-	    *timerid = (timer_t) newp;
-	    return 0;
+	    free (newp);
+	    return -1;
 	  }
 
-	/* Free the resources.  */
-	free (newp);
+	/* Add to the queue of active timers with thread delivery.  */
+	__add_active_timer_sigev (newp);
 
-	__set_errno (INTERNAL_SYSCALL_ERRNO (res, err));
-
-	return -1;
+	*timerid = (timer_t) newp;
       }
-  }
+     break;
+
+   default:
+     __set_errno (-1);
+     return -1;
+   }
+
+  return 0;
 }
diff --git a/sysdeps/unix/sysv/linux/timer_delete.c b/sysdeps/unix/sysv/linux/timer_delete.c
index 3aec393132..ee5deb8739 100644
--- a/sysdeps/unix/sysv/linux/timer_delete.c
+++ b/sysdeps/unix/sysv/linux/timer_delete.c
@@ -16,7 +16,6 @@ 
    License along with the GNU C Library; see the file COPYING.LIB.  If
    not, see <https://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
 #include <stdlib.h>
 #include <time.h>
 #include <sysdep.h>
@@ -35,38 +34,17 @@  timer_delete (timer_t timerid)
   struct timer *kt = (struct timer *) timerid;
 
   /* Delete the kernel timer object.  */
-  int res = INLINE_SYSCALL (timer_delete, 1, kt->ktimerid);
+  int r = INLINE_SYSCALL_CALL (timer_delete, kt->ktimerid);
+  if (r != 0)
+    /* The kernel timer is not known or something else bad happened.
+       Return the error.  */
+    return -1;
 
-  if (res == 0)
-    {
-      if (kt->sigev_notify == SIGEV_THREAD)
-	{
-	  /* Remove the timer from the list.  */
-	  pthread_mutex_lock (&__active_timer_sigev_thread_lock);
-	  if (__active_timer_sigev_thread == kt)
-	    __active_timer_sigev_thread = kt->next;
-	  else
-	    {
-	      struct timer *prevp = __active_timer_sigev_thread;
-	      while (prevp->next != NULL)
-		if (prevp->next == kt)
-		  {
-		    prevp->next = kt->next;
-		    break;
-		  }
-		else
-		  prevp = prevp->next;
-	    }
-	  pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
-	}
+  if (kt->sigev_notify == SIGEV_THREAD)
+    __remove_active_timer_sigev (kt);
 
-      /* Free the memory.  */
-      (void) free (kt);
+  /* Free the memory.  */
+  free (kt);
 
-      return 0;
-    }
-
-  /* The kernel timer is not known or something else bad happened.
-     Return the error.  */
-  return -1;
+  return 0;
 }
diff --git a/sysdeps/unix/sysv/linux/timer_getoverr.c b/sysdeps/unix/sysv/linux/timer_getoverr.c
index 04122a9878..82627e4ee3 100644
--- a/sysdeps/unix/sysv/linux/timer_getoverr.c
+++ b/sysdeps/unix/sysv/linux/timer_getoverr.c
@@ -34,7 +34,7 @@  timer_getoverrun (timer_t timerid)
   struct timer *kt = (struct timer *) timerid;
 
   /* Get the information from the kernel.  */
-  int res = INLINE_SYSCALL (timer_getoverrun, 1, kt->ktimerid);
+  int res = INLINE_SYSCALL_CALL (timer_getoverrun, kt->ktimerid);
 
   return res;
 }
diff --git a/sysdeps/unix/sysv/linux/timer_routines.c b/sysdeps/unix/sysv/linux/timer_routines.c
index 98bbe077fa..97882f036b 100644
--- a/sysdeps/unix/sysv/linux/timer_routines.c
+++ b/sysdeps/unix/sysv/linux/timer_routines.c
@@ -16,19 +16,20 @@ 
    License along with the GNU C Library; see the file COPYING.LIB.  If
    not, see <https://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <setjmp.h>
+#include <pthread.h>
 #include <signal.h>
-#include <stdbool.h>
-#include <sysdep-cancel.h>
+#include <stdlib.h>
+
+#include <kernel-posix-timers.h>
+#include <internal-signals.h>
 #include <nptl/pthreadP.h>
-#include "kernel-posix-timers.h"
 
 
 /* List of active SIGEV_THREAD timers.  */
-struct timer *__active_timer_sigev_thread;
+static struct timer *__active_timer_sigev_thread;
 /* Lock for the __active_timer_sigev_thread.  */
-pthread_mutex_t __active_timer_sigev_thread_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t __active_timer_sigev_thread_lock
+  = PTHREAD_MUTEX_INITIALIZER;
 
 
 struct thread_start_data
@@ -56,6 +57,41 @@  timer_sigev_thread (void *arg)
   return NULL;
 }
 
+/* Append a new time KT on the on the active list __active_timer_sigev_thread
+   list in a thread safe way.  */
+void
+__add_active_timer_sigev (struct timer *kt)
+{
+  pthread_mutex_lock (&__active_timer_sigev_thread_lock);
+  kt->next = __active_timer_sigev_thread;
+  __active_timer_sigev_thread = kt;
+  pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
+}
+
+/* Remove the active timer KT on the active list __active_timer_sigev_thread
+   list in a thread safe way.  */
+void
+__remove_active_timer_sigev (struct timer *kt)
+{
+  /* Remove the timer from the list.  */
+  pthread_mutex_lock (&__active_timer_sigev_thread_lock);
+  if (__active_timer_sigev_thread == kt)
+    __active_timer_sigev_thread = kt->next;
+  else
+    {
+      struct timer *prevp = __active_timer_sigev_thread;
+      while (prevp->next != NULL)
+	if (prevp->next == kt)
+	  {
+	    prevp->next = kt->next;
+	    break;
+	  }
+	else
+	  prevp = prevp->next;
+    }
+  pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
+}
+
 
 /* Helper function to support starting threads for SIGEV_THREAD.  */
 static void *