diff options
Diffstat (limited to 'linuxthreads')
-rw-r--r-- | linuxthreads/ChangeLog | 33 | ||||
-rw-r--r-- | linuxthreads/sysdeps/pthread/posix-timer.h | 28 | ||||
-rw-r--r-- | linuxthreads/sysdeps/pthread/timer_getoverr.c | 4 | ||||
-rw-r--r-- | linuxthreads/sysdeps/pthread/timer_gettime.c | 35 | ||||
-rw-r--r-- | linuxthreads/sysdeps/pthread/timer_routines.c | 12 | ||||
-rw-r--r-- | linuxthreads/sysdeps/pthread/timer_settime.c | 13 |
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: |