about summary refs log tree commit diff
path: root/linuxthreads
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-06-20 00:34:21 +0000
committerUlrich Drepper <drepper@redhat.com>2000-06-20 00:34:21 +0000
commitd2dfc5de011fb525161b85a1408f716a2ea358cc (patch)
tree22804aa59f348ac9d5bf432d2ddeb4c79ad31910 /linuxthreads
parentd620426811688301eb1cbe6e63773d6430b2706e (diff)
downloadglibc-d2dfc5de011fb525161b85a1408f716a2ea358cc.tar.gz
glibc-d2dfc5de011fb525161b85a1408f716a2ea358cc.tar.xz
glibc-d2dfc5de011fb525161b85a1408f716a2ea358cc.zip
Update.
	* iconv/gconv_int.h (strict gconv_module): Remove all members
	associated with regular expressions.  Use a simple string as the
	from name.
	* iconv/gconv_db.c: Remove code handling regular expressions.
	* iconv/gconv_conf.c: Likewise.
	* iconv/iconv_prog.c: Likewise.
	* iconv/gconv_builtin.h: Adjust for change in gconv_conf.c.
Diffstat (limited to 'linuxthreads')
-rw-r--r--linuxthreads/ChangeLog33
-rw-r--r--linuxthreads/sysdeps/pthread/posix-timer.h28
-rw-r--r--linuxthreads/sysdeps/pthread/timer_getoverr.c4
-rw-r--r--linuxthreads/sysdeps/pthread/timer_gettime.c35
-rw-r--r--linuxthreads/sysdeps/pthread/timer_routines.c12
-rw-r--r--linuxthreads/sysdeps/pthread/timer_settime.c13
6 files changed, 96 insertions, 29 deletions
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 2322ca91e6..0402c0fdfe 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,36 @@
+2000-06-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/timer_create.c: Use _set_errno instead of assigning
+	to errno directly.
+	* sysdeps/pthread/timer_delete.c: Likewise.
+	* sysdeps/pthread/timer_getoverr.c: Likewise.
+	* sysdeps/pthread/timer_gettime.c: Likewise.
+	* sysdeps/pthread/timer_settime.c: Likewise.
+
+2000-06-13  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	Timer nodes are now reference counted, and can be marked
+	as deleted. This allows for the safe release of the global mutex
+	in the middle without losing the timer being operated on.
+
+	* sysdeps/pthread/posix-timer.h (struct timer_node):  The inuse
+	member is now an enum with three values, so that an intermediate
+	state can be represented (deleted but not free for reuse yet).
+	New refcount member added.
+	* sysdeps/pthread/timer_routines.c: Likewise.
+
+	* sysdeps/pthread/posix-timer.h (timer_addref, timer_delref,
+	timer_valid): New inline functions added.
+
+	* sysdeps/pthread/timer_gettime.c (timer_gettime): Function
+	restructured, recursive deadlock bug fixed.
+
+	* sysdeps/pthread/timer_gettime.c (timer_gettime): Uses new
+	timer_addref to ensure that timer won't be deleted while mutex is not
+	held. Also uses timer_invalid to perform validation of timer handle.
+	* sysdeps/pthread/timer_settime.c (timer_settime): Likewise.
+	* sysdeps/pthread/timer_getoverr.c (timer_getoverrun): Likewise.
+
 2000-06-14  Ulrich Drepper  <drepper@redhat.com>
 
 	* shlib-versions: Add entry for SH.
diff --git a/linuxthreads/sysdeps/pthread/posix-timer.h b/linuxthreads/sysdeps/pthread/posix-timer.h
index feeff39fa8..7a2caf28a4 100644
--- a/linuxthreads/sysdeps/pthread/posix-timer.h
+++ b/linuxthreads/sysdeps/pthread/posix-timer.h
@@ -59,9 +59,12 @@ struct timer_node
   pthread_attr_t attr;
   unsigned int abstime;
   unsigned int armed;
-  unsigned int inuse;
+  enum {
+    TIMER_FREE, TIMER_INUSE, TIMER_DELETED
+  } inuse;
   struct thread_node *thread;
   pid_t creator_pid;
+  int refcount;
 };
 
 
@@ -106,6 +109,28 @@ timer_ptr2id (struct timer_node *timer)
   return timer - __timer_array;
 }
 
+/* Check whether timer is valid; global mutex must be held. */
+static inline int
+timer_valid (struct timer_node *timer)
+{
+  return timer && timer->inuse == TIMER_INUSE;
+}
+
+/* Timer refcount functions; need global mutex. */
+extern void __timer_dealloc (struct timer_node *timer);
+
+static inline void
+timer_addref (struct timer_node *timer)
+{
+  timer->refcount++;
+}
+
+static inline void
+timer_delref (struct timer_node *timer)
+{
+  if (--timer->refcount == 0)
+    __timer_dealloc (timer);
+}
 
 /* Timespec helper routines.  */
 static inline int
@@ -178,7 +203,6 @@ extern struct timer_node *__timer_alloc (void);
 extern int __timer_thread_start (struct thread_node *thread);
 extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t);
 extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t);
-extern void __timer_dealloc (struct timer_node *timer);
 extern void __timer_thread_dealloc (struct thread_node *thread);
 extern int __timer_thread_queue_timer (struct thread_node *thread,
 				       struct timer_node *insert);
diff --git a/linuxthreads/sysdeps/pthread/timer_getoverr.c b/linuxthreads/sysdeps/pthread/timer_getoverr.c
index 8630f57829..520458c712 100644
--- a/linuxthreads/sysdeps/pthread/timer_getoverr.c
+++ b/linuxthreads/sysdeps/pthread/timer_getoverr.c
@@ -34,8 +34,8 @@ timer_getoverrun (timerid)
 
   pthread_mutex_lock (&__timer_mutex);
 
-  if ((timer = timer_id2ptr (timerid)) == NULL || !timer->inuse)
-    errno = EINVAL;
+  if (! timer_valid (timer = timer_id2ptr (timerid)))
+    __set_errno (EINVAL);
   else
     retval = 0; /* TODO: overrun counting not supported */
 
diff --git a/linuxthreads/sysdeps/pthread/timer_gettime.c b/linuxthreads/sysdeps/pthread/timer_gettime.c
index 43b07598b7..dbee9d915e 100644
--- a/linuxthreads/sysdeps/pthread/timer_gettime.c
+++ b/linuxthreads/sysdeps/pthread/timer_gettime.c
@@ -31,25 +31,30 @@ timer_gettime (timerid, value)
      struct itimerspec *value;
 {
   struct timer_node *timer;
-  struct timespec now;
-  int retval = -1;
+  struct timespec now, expiry;
+  int retval = -1, armed = 0, valid;
+  clock_t clock = 0;
 
   pthread_mutex_lock (&__timer_mutex);
 
   timer = timer_id2ptr (timerid);
-  if (timer == NULL && !timer->inuse)
-    /* Invalid timer ID or the timer is not in use.  */
-    errno = EINVAL;
-  else
-    {
-      value->it_interval = timer->value.it_interval;
+  valid = timer_valid (timer);
+
+  if (valid) {
+    armed = timer->armed;
+    expiry = timer->expirytime;
+    clock = timer->clock;
+    value->it_interval = timer->value.it_interval;
+  }
+
+  pthread_mutex_unlock (&__timer_mutex);
 
-      if (timer->armed)
+  if (valid)
+    {
+      if (armed)
 	{
-	  pthread_mutex_unlock (&__timer_mutex);
-	  clock_gettime (timer->clock, &now);
-	  pthread_mutex_lock (&__timer_mutex);
-	  timespec_sub (&value->it_value, &timer->expirytime, &now);
+	  clock_gettime (clock, &now);
+	  timespec_sub (&value->it_value, &expiry, &now);
 	}
       else
 	{
@@ -59,8 +64,8 @@ timer_gettime (timerid, value)
 
       retval = 0;
     }
-
-  pthread_mutex_lock (&__timer_mutex);
+  else
+    __set_errno (EINVAL);
 
   return retval;
 }
diff --git a/linuxthreads/sysdeps/pthread/timer_routines.c b/linuxthreads/sysdeps/pthread/timer_routines.c
index ddf02fadd6..2d4e325b6d 100644
--- a/linuxthreads/sysdeps/pthread/timer_routines.c
+++ b/linuxthreads/sysdeps/pthread/timer_routines.c
@@ -181,7 +181,7 @@ init_module (void)
   for (i = 0; i < TIMER_MAX; ++i)
     {
       list_append (&timer_free_list, &__timer_array[i].links);
-      __timer_array[i].inuse = 0;
+      __timer_array[i].inuse = TIMER_FREE;
     }
 
   for (i = 0; i < THREAD_MAXNODES; ++i)
@@ -309,7 +309,7 @@ thread_cleanup (void *val)
 static void
 thread_expire_timer (struct thread_node *self, struct timer_node *timer)
 {
-  self->current_timer = timer;
+  self->current_timer = timer; /* Lets timer_delete know timer is running. */
 
   pthread_mutex_unlock (&__timer_mutex);
 
@@ -443,7 +443,7 @@ thread_func (void *arg)
 }
 
 
-/* Enqueue a timer in wakeup order in the thread's timer queue. 
+/* Enqueue a timer in wakeup order in the thread's timer queue.
    Returns 1 if the timer was inserted at the head of the queue,
    causing the queue's next wakeup time to change. */
 
@@ -551,7 +551,8 @@ __timer_alloc (void)
     {
       struct timer_node *timer = timer_links2ptr (node);
       list_unlink_ip (node);
-      timer->inuse = 1;
+      timer->inuse = TIMER_INUSE;
+      timer->refcount = 1;
       return timer;
     }
 
@@ -564,8 +565,9 @@ __timer_alloc (void)
 void
 __timer_dealloc (struct timer_node *timer)
 {
+  assert (timer->refcount == 0);
   timer->thread = NULL;	/* Break association between timer and thread.  */
-  timer->inuse = 0;
+  timer->inuse = TIMER_FREE;
   list_append (&timer_free_list, &timer->links);
 }
 
diff --git a/linuxthreads/sysdeps/pthread/timer_settime.c b/linuxthreads/sysdeps/pthread/timer_settime.c
index 858edc7657..e6c35b4fcf 100644
--- a/linuxthreads/sysdeps/pthread/timer_settime.c
+++ b/linuxthreads/sysdeps/pthread/timer_settime.c
@@ -41,7 +41,7 @@ timer_settime (timerid, flags, value, ovalue)
   timer = timer_id2ptr (timerid);
   if (timer == NULL)
     {
-      errno = EINVAL;
+      __set_errno (EINVAL);
       goto bail;
     }
 
@@ -50,7 +50,7 @@ timer_settime (timerid, flags, value, ovalue)
       || value->it_value.tv_nsec < 0
       || value->it_value.tv_nsec >= 1000000000)
     {
-      errno = EINVAL;
+      __set_errno (EINVAL);
       goto bail;
     }
 
@@ -64,13 +64,14 @@ timer_settime (timerid, flags, value, ovalue)
     }
 
   pthread_mutex_lock (&__timer_mutex);
+  timer_addref (timer);
 
   /* One final check of timer validity; this one is possible only
-     until we have the mutex, which guards the inuse flag. */
+     until we have the mutex, because it accesses the inuse flag. */
 
-  if (!timer->inuse)
+  if (! timer_valid(timer))
     {
-      errno = EINVAL;
+      __set_errno (EINVAL);
       goto unlock_bail;
     }
 
@@ -86,6 +87,7 @@ timer_settime (timerid, flags, value, ovalue)
 	      clock_gettime (timer->clock, &now);
 	      have_now = 1;
 	      pthread_mutex_lock (&__timer_mutex);
+	      timer_addref (timer);
 	    }
 
 	  timespec_sub (&ovalue->it_value, &timer->expirytime, &now);
@@ -123,6 +125,7 @@ timer_settime (timerid, flags, value, ovalue)
   retval = 0;
 
 unlock_bail:
+  timer_delref (timer);
   pthread_mutex_unlock (&__timer_mutex);
 
 bail: