mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-27 03:41:23 +08:00
Update.
2000-06-10 Kaz Kylheku <kaz@ashi.footprints.net> * sysdeps/pthread/timer_create.c: Thread matching now done on clock type as well as thread attributes. There are individual global signal-delivering threads for different clock types. * sysdeps/pthread/posix-timer.h: Likewise. * sysdeps/pthread/timer_routines.c: Likewise. * sysdeps/pthread/timer_routines.c: Thread allocation and deallocation function now remembers to put thread on active list and remove from active list. Thus now the feature of binding multiple timers to a single thread actually works.
This commit is contained in:
parent
15109bd4aa
commit
45dc1187ee
@ -1,3 +1,18 @@
|
|||||||
|
2000-06-10 Kaz Kylheku <kaz@ashi.footprints.net>
|
||||||
|
|
||||||
|
* sysdeps/pthread/timer_create.c: Thread matching now done on
|
||||||
|
clock type as well as thread attributes.
|
||||||
|
There are individual global signal-delivering threads for
|
||||||
|
different clock types.
|
||||||
|
* sysdeps/pthread/posix-timer.h: Likewise.
|
||||||
|
* sysdeps/pthread/timer_routines.c: Likewise.
|
||||||
|
|
||||||
|
* sysdeps/pthread/timer_routines.c: Thread allocation and
|
||||||
|
deallocation function now remembers to put thread on active
|
||||||
|
list and remove from active list.
|
||||||
|
Thus now the feature of binding multiple timers
|
||||||
|
to a single thread actually works.
|
||||||
|
|
||||||
2000-06-10 Ulrich Drepper <drepper@redhat.com>
|
2000-06-10 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* pthread.c (__pthread_create_2_1): Optimize a bit.
|
* pthread.c (__pthread_create_2_1): Optimize a bit.
|
||||||
|
@ -44,6 +44,7 @@ struct thread_node
|
|||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
struct timer_node *current_timer;
|
struct timer_node *current_timer;
|
||||||
pthread_t captured;
|
pthread_t captured;
|
||||||
|
clockid_t clock_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -76,8 +77,16 @@ extern pthread_once_t __timer_init_once_control;
|
|||||||
/* Nonzero if initialization of timer implementation failed. */
|
/* Nonzero if initialization of timer implementation failed. */
|
||||||
extern int __timer_init_failed;
|
extern int __timer_init_failed;
|
||||||
|
|
||||||
/* Node for the thread used to deliver signals. */
|
/* Nodes for the threads used to deliver signals. */
|
||||||
extern struct thread_node __timer_signal_thread;
|
/* A distinct thread is used for each clock type. */
|
||||||
|
|
||||||
|
extern struct thread_node __timer_signal_thread_rclk;
|
||||||
|
#ifdef _POSIX_CPUTIME
|
||||||
|
extern struct thread_node __timer_signal_thread_pclk;
|
||||||
|
#endif
|
||||||
|
#ifdef _POSIX_THREAD_CPUTIME
|
||||||
|
extern struct thread_node __timer_signal_thread_tclk;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Return pointer to timer structure corresponding to ID. */
|
/* Return pointer to timer structure corresponding to ID. */
|
||||||
@ -160,10 +169,10 @@ extern void __timer_mutex_cancel_handler (void *arg);
|
|||||||
extern void __timer_init_once (void);
|
extern void __timer_init_once (void);
|
||||||
extern struct timer_node *__timer_alloc (void);
|
extern struct timer_node *__timer_alloc (void);
|
||||||
extern int __timer_thread_start (struct thread_node *thread);
|
extern int __timer_thread_start (struct thread_node *thread);
|
||||||
extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr);
|
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);
|
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_dealloc (struct timer_node *timer);
|
||||||
extern void __timer_thread_dealloc (struct thread_node *thread);
|
extern void __timer_thread_dealloc (struct thread_node *thread);
|
||||||
extern int __timer_thread_queue_timer (struct thread_node *thread,
|
extern void __timer_thread_queue_timer (struct thread_node *thread,
|
||||||
struct timer_node *insert);
|
struct timer_node *insert);
|
||||||
extern void __timer_thread_wakeup (struct thread_node *thread);
|
extern void __timer_thread_wakeup (struct thread_node *thread);
|
||||||
|
@ -89,16 +89,33 @@ timer_create (clock_id, evp, timerid)
|
|||||||
case SIGEV_SIGNAL:
|
case SIGEV_SIGNAL:
|
||||||
/* We have a global thread for delivering timed signals.
|
/* We have a global thread for delivering timed signals.
|
||||||
If it is not running, try to start it up. */
|
If it is not running, try to start it up. */
|
||||||
if (! __timer_signal_thread.exists)
|
switch (clock_id)
|
||||||
{
|
{
|
||||||
if (__builtin_expect (__timer_thread_start (&__timer_signal_thread),
|
case CLOCK_REALTIME:
|
||||||
|
default:
|
||||||
|
thread = &__timer_signal_thread_rclk;
|
||||||
|
break;
|
||||||
|
#ifdef _POSIX_CPUTIME
|
||||||
|
case CLOCK_PROCESS_CPUTIME_ID:
|
||||||
|
thread = &__timer_signal_thread_pclk;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef _POSIX_THREAD_CPUTIME
|
||||||
|
case CLOCK_THREAD_CPUTIME_ID:
|
||||||
|
thread = &__timer_signal_thread_tclk;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! thread->exists)
|
||||||
|
{
|
||||||
|
if (__builtin_expect (__timer_thread_start (thread),
|
||||||
1) < 0)
|
1) < 0)
|
||||||
{
|
{
|
||||||
errno = EAGAIN;
|
errno = EAGAIN;
|
||||||
goto unlock_bail;
|
goto unlock_bail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thread = &__timer_signal_thread;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGEV_THREAD:
|
case SIGEV_THREAD:
|
||||||
@ -112,11 +129,11 @@ timer_create (clock_id, evp, timerid)
|
|||||||
pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED);
|
pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
|
||||||
/* Try to find existing thread having the right attributes. */
|
/* Try to find existing thread having the right attributes. */
|
||||||
thread = __timer_thread_find_matching (&newtimer->attr);
|
thread = __timer_thread_find_matching (&newtimer->attr, clock_id);
|
||||||
|
|
||||||
/* If no existing thread has these attributes, try to allocate one. */
|
/* If no existing thread has these attributes, try to allocate one. */
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
thread = __timer_thread_alloc (&newtimer->attr);
|
thread = __timer_thread_alloc (&newtimer->attr, clock_id);
|
||||||
|
|
||||||
/* Out of luck; no threads are available. */
|
/* Out of luck; no threads are available. */
|
||||||
if (__builtin_expect (thread == NULL, 0))
|
if (__builtin_expect (thread == NULL, 0))
|
||||||
|
@ -49,7 +49,13 @@ pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT;
|
|||||||
int __timer_init_failed;
|
int __timer_init_failed;
|
||||||
|
|
||||||
/* Node for the thread used to deliver signals. */
|
/* Node for the thread used to deliver signals. */
|
||||||
struct thread_node __timer_signal_thread;
|
struct thread_node __timer_signal_thread_rclk;
|
||||||
|
#ifdef _POSIX_CPUTIME
|
||||||
|
struct thread_node __timer_signal_thread_pclk;
|
||||||
|
#endif
|
||||||
|
#ifdef _POSIX_THREAD_CPUTIME
|
||||||
|
struct thread_node __timer_signal_thread_tclk;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Lists to keep free and used timers and threads. */
|
/* Lists to keep free and used timers and threads. */
|
||||||
struct list_links timer_free_list;
|
struct list_links timer_free_list;
|
||||||
@ -127,7 +133,7 @@ timer_links2ptr (struct list_links *list)
|
|||||||
|
|
||||||
/* Initialize a newly allocated thread structure. */
|
/* Initialize a newly allocated thread structure. */
|
||||||
static void
|
static void
|
||||||
thread_init (struct thread_node *thread, const pthread_attr_t *attr)
|
thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id)
|
||||||
{
|
{
|
||||||
if (attr != NULL)
|
if (attr != NULL)
|
||||||
thread->attr = *attr;
|
thread->attr = *attr;
|
||||||
@ -142,6 +148,7 @@ thread_init (struct thread_node *thread, const pthread_attr_t *attr)
|
|||||||
pthread_cond_init (&thread->cond, 0);
|
pthread_cond_init (&thread->cond, 0);
|
||||||
thread->current_timer = 0;
|
thread->current_timer = 0;
|
||||||
thread->captured = pthread_self ();
|
thread->captured = pthread_self ();
|
||||||
|
thread->clock_id = clock_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -166,7 +173,13 @@ init_module (void)
|
|||||||
for (i = 0; i < THREAD_MAXNODES; ++i)
|
for (i = 0; i < THREAD_MAXNODES; ++i)
|
||||||
list_append (&thread_free_list, &thread_array[i].links);
|
list_append (&thread_free_list, &thread_array[i].links);
|
||||||
|
|
||||||
thread_init (&__timer_signal_thread, 0);
|
thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME);
|
||||||
|
#ifdef _POSIX_CPUTIME
|
||||||
|
thread_init (&__timer_signal_thread_pclk, 0, CLOCK_PROCESS_CPUTIME_ID);
|
||||||
|
#endif
|
||||||
|
#ifdef _POSIX_THREAD_CPUTIME
|
||||||
|
thread_init (&__timer_signal_thread_tclk, 0, CLOCK_THREAD_CPUTIME_ID);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -203,9 +216,10 @@ thread_deinit (struct thread_node *thread)
|
|||||||
|
|
||||||
|
|
||||||
/* Allocate a thread structure from the global free list. Global
|
/* Allocate a thread structure from the global free list. Global
|
||||||
mutex lock must be held by caller. */
|
mutex lock must be held by caller. The thread is moved to
|
||||||
|
the active list. */
|
||||||
struct thread_node *
|
struct thread_node *
|
||||||
__timer_thread_alloc (const pthread_attr_t *desired_attr)
|
__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id)
|
||||||
{
|
{
|
||||||
struct list_links *node = list_first (&thread_free_list);
|
struct list_links *node = list_first (&thread_free_list);
|
||||||
|
|
||||||
@ -213,7 +227,8 @@ __timer_thread_alloc (const pthread_attr_t *desired_attr)
|
|||||||
{
|
{
|
||||||
struct thread_node *thread = thread_links2ptr (node);
|
struct thread_node *thread = thread_links2ptr (node);
|
||||||
list_unlink (node);
|
list_unlink (node);
|
||||||
thread_init (thread, desired_attr);
|
thread_init (thread, desired_attr, clock_id);
|
||||||
|
list_append (&thread_active_list, node);
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,6 +242,7 @@ void
|
|||||||
__timer_thread_dealloc (struct thread_node *thread)
|
__timer_thread_dealloc (struct thread_node *thread)
|
||||||
{
|
{
|
||||||
thread_deinit (thread);
|
thread_deinit (thread);
|
||||||
|
list_unlink (&thread->links);
|
||||||
list_append (&thread_free_list, &thread->links);
|
list_append (&thread_free_list, &thread->links);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +263,13 @@ thread_cleanup (void *val)
|
|||||||
struct thread_node *thread = val;
|
struct thread_node *thread = val;
|
||||||
|
|
||||||
/* How did the signal thread get killed? */
|
/* How did the signal thread get killed? */
|
||||||
assert (thread != &__timer_signal_thread);
|
assert (thread != &__timer_signal_thread_rclk);
|
||||||
|
#ifdef _POSIX_CPUTIME
|
||||||
|
assert (thread != &__timer_signal_thread_pclk);
|
||||||
|
#endif
|
||||||
|
#ifdef _POSIX_THREAD_CPUTIME
|
||||||
|
assert (thread != &__timer_signal_thread_tclk);
|
||||||
|
#endif
|
||||||
|
|
||||||
pthread_mutex_lock (&__timer_mutex);
|
pthread_mutex_lock (&__timer_mutex);
|
||||||
|
|
||||||
@ -379,7 +401,7 @@ thread_func (void *arg)
|
|||||||
{
|
{
|
||||||
timespec_add (&timer->expirytime, &now,
|
timespec_add (&timer->expirytime, &now,
|
||||||
&timer->value.it_interval);
|
&timer->value.it_interval);
|
||||||
(void) __timer_thread_queue_timer (self, timer);
|
__timer_thread_queue_timer (self, timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_expire_timer (self, timer);
|
thread_expire_timer (self, timer);
|
||||||
@ -411,40 +433,23 @@ 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. */
|
||||||
int
|
void
|
||||||
__timer_thread_queue_timer (struct thread_node *thread,
|
__timer_thread_queue_timer (struct thread_node *thread,
|
||||||
struct timer_node *insert)
|
struct timer_node *insert)
|
||||||
{
|
{
|
||||||
struct list_links *iter;
|
struct list_links *iter;
|
||||||
struct list_links *matching = NULL;
|
|
||||||
struct timer_node *timer = NULL;
|
|
||||||
|
|
||||||
for (iter = list_first (&thread->timer_queue);
|
for (iter = list_first (&thread->timer_queue);
|
||||||
iter != list_null (&thread->timer_queue);
|
iter != list_null (&thread->timer_queue);
|
||||||
iter = list_next (iter))
|
iter = list_next (iter))
|
||||||
{
|
{
|
||||||
timer = timer_links2ptr (iter);
|
struct timer_node *timer = timer_links2ptr (iter);
|
||||||
|
|
||||||
if (insert->clock == timer->clock)
|
if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0)
|
||||||
{
|
break;
|
||||||
matching = iter;
|
|
||||||
if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timer != NULL && insert->clock != timer->clock)
|
|
||||||
{
|
|
||||||
if (matching == NULL)
|
|
||||||
/* We cannot queue this timer. */
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
iter = matching;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
list_insbefore (iter, &insert->links);
|
list_insbefore (iter, &insert->links);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -495,7 +500,8 @@ thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right)
|
|||||||
/* Search the list of active threads and find one which has matching
|
/* Search the list of active threads and find one which has matching
|
||||||
attributes. Global mutex lock must be held by caller. */
|
attributes. Global mutex lock must be held by caller. */
|
||||||
struct thread_node *
|
struct thread_node *
|
||||||
__timer_thread_find_matching (const pthread_attr_t *desired_attr)
|
__timer_thread_find_matching (const pthread_attr_t *desired_attr,
|
||||||
|
clockid_t desired_clock_id)
|
||||||
{
|
{
|
||||||
struct list_links *iter = list_first (&thread_active_list);
|
struct list_links *iter = list_first (&thread_active_list);
|
||||||
|
|
||||||
@ -503,7 +509,8 @@ __timer_thread_find_matching (const pthread_attr_t *desired_attr)
|
|||||||
{
|
{
|
||||||
struct thread_node *candidate = thread_links2ptr (iter);
|
struct thread_node *candidate = thread_links2ptr (iter);
|
||||||
|
|
||||||
if (thread_attr_compare (desired_attr, &candidate->attr))
|
if (thread_attr_compare (desired_attr, &candidate->attr)
|
||||||
|
&& desired_clock_id == candidate->clock_id)
|
||||||
{
|
{
|
||||||
list_unlink (iter);
|
list_unlink (iter);
|
||||||
return candidate;
|
return candidate;
|
||||||
|
Loading…
Reference in New Issue
Block a user