Back to index

glibc  2.9
Defines | Functions | Variables
timer_routines.c File Reference
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sysdep.h>
#include <time.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "posix-timer.h"
#include <pthreadP.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define THREAD_MAXNODES   16

Functions

static void list_init (struct list_links *list)
static void list_append (struct list_links *list, struct list_links *newp)
static void list_insbefore (struct list_links *list, struct list_links *newp)
static void list_unlink (struct list_links *list)
static struct list_linkslist_first (struct list_links *list)
static struct list_linkslist_null (struct list_links *list)
static struct list_linkslist_next (struct list_links *list)
static int list_isempty (struct list_links *list)
static struct thread_nodethread_links2ptr (struct list_links *list)
static struct timer_nodetimer_links2ptr (struct list_links *list)
static void thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id)
static void init_module (void)
static void reinit_after_fork (void)
void __timer_init_once (void)
static void thread_deinit (struct thread_node *thread)
struct thread_node__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id)
void __timer_thread_dealloc (struct thread_node *thread)
static void thread_cleanup (void *val)
static void thread_expire_timer (struct thread_node *self, struct timer_node *timer)
static void __attribute__ ((noreturn))
int __timer_thread_queue_timer (struct thread_node *thread, struct timer_node *insert)
int __timer_thread_start (struct thread_node *thread)
void __timer_thread_wakeup (struct thread_node *thread)
static int thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right)
struct thread_node__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t desired_clock_id)
struct timer_node__timer_alloc (void)
void __timer_dealloc (struct timer_node *timer)
void __timer_mutex_cancel_handler (void *arg)

Variables

static struct thread_node [THREAD_MAXNODES]
pthread_mutex_t __timer_mutex = PTHREAD_MUTEX_INITIALIZER
pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT
int __timer_init_failed

Define Documentation

#define THREAD_MAXNODES   16

Definition at line 37 of file timer_routines.c.


Function Documentation

static void __attribute__ ( (noreturn)  ) [static]

Definition at line 355 of file timer_routines.c.

{
  struct thread_node *self = arg;

  /* Register cleanup handler, in case rogue application terminates
     this thread.  (This cannot happen to __timer_signal_thread, which
     doesn't invoke application callbacks). */

  pthread_cleanup_push (thread_cleanup, self);

  pthread_mutex_lock (&__timer_mutex);

  while (1)
    {
      struct list_links *first;
      struct timer_node *timer = NULL;

      /* While the timer queue is not empty, inspect the first node.  */
      first = list_first (&self->timer_queue);
      if (first != list_null (&self->timer_queue))
       {
         struct timespec now;

         timer = timer_links2ptr (first);

         /* This assumes that the elements of the list of one thread
            are all for the same clock.  */
         clock_gettime (timer->clock, &now);

         while (1)
           {
             /* If the timer is due or overdue, remove it from the queue.
               If it's a periodic timer, re-compute its new time and
               requeue it.  Either way, perform the timer expiry. */
             if (timespec_compare (&now, &timer->expirytime) < 0)
              break;

             list_unlink_ip (first);

             if (__builtin_expect (timer->value.it_interval.tv_sec, 0) != 0
                || timer->value.it_interval.tv_nsec != 0)
              {
                timer->overrun_count = 0;
                timespec_add (&timer->expirytime, &timer->expirytime,
                            &timer->value.it_interval);
                while (timespec_compare (&timer->expirytime, &now) < 0)
                  {
                    timespec_add (&timer->expirytime, &timer->expirytime,
                                &timer->value.it_interval);
                    if (timer->overrun_count < DELAYTIMER_MAX)
                     ++timer->overrun_count;
                  }
                __timer_thread_queue_timer (self, timer);
              }

             thread_expire_timer (self, timer);

             first = list_first (&self->timer_queue);
             if (first == list_null (&self->timer_queue))
              break;

             timer = timer_links2ptr (first);
           }
       }

      /* If the queue is not empty, wait until the expiry time of the
        first node.  Otherwise wait indefinitely.  Insertions at the
        head of the queue must wake up the thread by broadcasting
        this condition variable.  */
      if (timer != NULL)
       pthread_cond_timedwait (&self->cond, &__timer_mutex,
                            &timer->expirytime);
      else
       pthread_cond_wait (&self->cond, &__timer_mutex);
    }
  /* This macro will never be executed since the while loop loops
     forever - but we have to add it for proper nesting.  */
  pthread_cleanup_pop (1);
}

Here is the call graph for this function:

struct timer_node* __timer_alloc ( void  ) [read]

Definition at line 544 of file timer_routines.c.

{
  struct list_links *node = list_first (&timer_free_list);

  if (node != list_null (&timer_free_list))
    {
      struct timer_node *timer = timer_links2ptr (node);
      list_unlink_ip (node);
      timer->inuse = TIMER_INUSE;
      timer->refcount = 1;
      return timer;
    }

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void __timer_dealloc ( struct timer_node timer)

Definition at line 564 of file timer_routines.c.

{
  assert (timer->refcount == 0);
  timer->thread = NULL;     /* Break association between timer and thread.  */
  timer->inuse = TIMER_FREE;
  list_append (&timer_free_list, &timer->links);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void __timer_init_once ( void  ) [read]

Definition at line 207 of file timer_routines.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void __timer_mutex_cancel_handler ( void *  arg)

Definition at line 575 of file timer_routines.c.

Here is the call graph for this function:

Here is the caller graph for this function:

struct thread_node* __timer_thread_alloc ( const pthread_attr_t desired_attr,
clockid_t  clock_id 
) [read]

Definition at line 227 of file timer_routines.c.

{
  struct list_links *node = list_first (&thread_free_list);

  if (node != list_null (&thread_free_list))
    {
      struct thread_node *thread = thread_links2ptr (node);
      list_unlink (node);
      thread_init (thread, desired_attr, clock_id);
      list_append (&thread_active_list, node);
      return thread;
    }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void __timer_thread_dealloc ( struct thread_node thread)

Definition at line 247 of file timer_routines.c.

{
  thread_deinit (thread);
  list_unlink (&thread->links);
  list_append (&thread_free_list, &thread->links);
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct thread_node* __timer_thread_find_matching ( const pthread_attr_t desired_attr,
clockid_t  desired_clock_id 
) [read]

Definition at line 521 of file timer_routines.c.

{
  struct list_links *iter = list_first (&thread_active_list);

  while (iter != list_null (&thread_active_list))
    {
      struct thread_node *candidate = thread_links2ptr (iter);

      if (thread_attr_compare (desired_attr, &candidate->attr)
         && desired_clock_id == candidate->clock_id)
       return candidate;

      iter = list_next (iter);
    }

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int __timer_thread_queue_timer ( struct thread_node thread,
struct timer_node insert 
)

Definition at line 442 of file timer_routines.c.

{
  struct list_links *iter;
  int athead = 1;

  for (iter = list_first (&thread->timer_queue);
       iter != list_null (&thread->timer_queue);
        iter = list_next (iter))
    {
      struct timer_node *timer = timer_links2ptr (iter);

      if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0)
         break;
      athead = 0;
    }

  list_insbefore (iter, &insert->links);
  return athead;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int __timer_thread_start ( struct thread_node thread)

Definition at line 467 of file timer_routines.c.

{
  int retval = 1;

  assert (!thread->exists);
  thread->exists = 1;

  if (pthread_create (&thread->id, &thread->attr,
                    (void *(*) (void *)) thread_func, thread) != 0)
    {
      thread->exists = 0;
      retval = -1;
    }

  return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void __timer_thread_wakeup ( struct thread_node thread)

Definition at line 486 of file timer_routines.c.

{
  pthread_cond_broadcast (&thread->cond);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void init_module ( void  ) [static]

Definition at line 170 of file timer_routines.c.

{
  int i;

  list_init (&timer_free_list);
  list_init (&thread_free_list);
  list_init (&thread_active_list);

  for (i = 0; i < TIMER_MAX; ++i)
    {
      list_append (&timer_free_list, &__timer_array[i].links);
      __timer_array[i].inuse = TIMER_FREE;
    }

  for (i = 0; i < THREAD_MAXNODES; ++i)
    list_append (&thread_free_list, &thread_array[i].links);

  thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void list_append ( struct list_links list,
struct list_links newp 
) [inline, static]

Definition at line 76 of file timer_routines.c.

{
  newp->prev = list->prev;
  newp->next = list;
  list->prev->next = newp;
  list->prev = newp;
}

Here is the caller graph for this function:

static struct list_links* list_first ( struct list_links list) [static, read]

Definition at line 105 of file timer_routines.c.

{
  return list->next;
}

Here is the caller graph for this function:

static void list_init ( struct list_links list) [inline, static]

Definition at line 70 of file timer_routines.c.

{
  list->next = list->prev = list;
}

Here is the caller graph for this function:

static void list_insbefore ( struct list_links list,
struct list_links newp 
) [inline, static]

Definition at line 85 of file timer_routines.c.

{
  list_append (list, newp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int list_isempty ( struct list_links list) [inline, static]

Definition at line 123 of file timer_routines.c.

{
  return list->next == list;
}

Here is the caller graph for this function:

static struct list_links* list_next ( struct list_links list) [static, read]

Definition at line 117 of file timer_routines.c.

{
  return list->next;
}

Here is the caller graph for this function:

static struct list_links* list_null ( struct list_links list) [static, read]

Definition at line 111 of file timer_routines.c.

{
  return list;
}

Here is the caller graph for this function:

static void list_unlink ( struct list_links list) [inline, static]

Definition at line 96 of file timer_routines.c.

{
  struct list_links *lnext = list->next, *lprev = list->prev;

  lnext->prev = lprev;
  lprev->next = lnext;
}

Here is the caller graph for this function:

static void reinit_after_fork ( void  ) [static]

Definition at line 196 of file timer_routines.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static int thread_attr_compare ( const pthread_attr_t left,
const pthread_attr_t right 
) [static]

Definition at line 498 of file timer_routines.c.

{
  struct pthread_attr *ileft = (struct pthread_attr *) left;
  struct pthread_attr *iright = (struct pthread_attr *) right;

  return (ileft->flags == iright->flags
         && ileft->schedpolicy == iright->schedpolicy
         && (ileft->schedparam.sched_priority
             == iright->schedparam.sched_priority)
         && ileft->guardsize == iright->guardsize
         && ileft->stackaddr == iright->stackaddr
         && ileft->stacksize == iright->stacksize
         && ((ileft->cpuset == NULL && iright->cpuset == NULL)
             || (ileft->cpuset != NULL && iright->cpuset != NULL
                && ileft->cpusetsize == iright->cpusetsize
                && memcmp (ileft->cpuset, iright->cpuset,
                          ileft->cpusetsize) == 0)));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void thread_cleanup ( void *  val) [static]

Definition at line 264 of file timer_routines.c.

{
  if (val != NULL)
    {
      struct thread_node *thread = val;

      /* How did the signal thread get killed?  */
      assert (thread != &__timer_signal_thread_rclk);

      pthread_mutex_lock (&__timer_mutex);

      thread->exists = 0;

      /* We are no longer processing a timer event.  */
      thread->current_timer = 0;

      if (list_isempty (&thread->timer_queue))
       __timer_thread_dealloc (thread);
      else
       (void) __timer_thread_start (thread);

      pthread_mutex_unlock (&__timer_mutex);

      /* Unblock potentially blocked timer_delete().  */
      pthread_cond_broadcast (&thread->cond);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void thread_deinit ( struct thread_node thread) [static]

Definition at line 216 of file timer_routines.c.

{
  assert (list_isempty (&thread->timer_queue));
  pthread_cond_destroy (&thread->cond);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void thread_expire_timer ( struct thread_node self,
struct timer_node timer 
) [static]

Definition at line 295 of file timer_routines.c.

{
  self->current_timer = timer; /* Lets timer_delete know timer is running. */

  pthread_mutex_unlock (&__timer_mutex);

  switch (__builtin_expect (timer->event.sigev_notify, SIGEV_SIGNAL))
    {
    case SIGEV_NONE:
      break;

    case SIGEV_SIGNAL:
#ifdef __NR_rt_sigqueueinfo
      {
       siginfo_t info;

       /* First, clear the siginfo_t structure, so that we don't pass our
          stack content to other tasks.  */
       memset (&info, 0, sizeof (siginfo_t));
       /* We must pass the information about the data in a siginfo_t
           value.  */
       info.si_signo = timer->event.sigev_signo;
       info.si_code = SI_TIMER;
       info.si_pid = timer->creator_pid;
       info.si_uid = getuid ();
       info.si_value = timer->event.sigev_value;

       INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, info.si_signo, &info);
      }
#else
      if (pthread_kill (self->captured, timer->event.sigev_signo) != 0)
       {
         if (pthread_kill (self->id, timer->event.sigev_signo) != 0)
           abort ();
        }
#endif
      break;

    case SIGEV_THREAD:
      timer->event.sigev_notify_function (timer->event.sigev_value);
      break;

    default:
      assert (! "unknown event");
      break;
    }

  pthread_mutex_lock (&__timer_mutex);

  self->current_timer = 0;

  pthread_cond_broadcast (&self->cond);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void thread_init ( struct thread_node thread,
const pthread_attr_t attr,
clockid_t  clock_id 
) [static]

Definition at line 147 of file timer_routines.c.

{
  if (attr != NULL)
    thread->attr = *attr;
  else
    {
      pthread_attr_init (&thread->attr);
      pthread_attr_setdetachstate (&thread->attr, PTHREAD_CREATE_DETACHED);
    }

  thread->exists = 0;
  list_init (&thread->timer_queue);
  pthread_cond_init (&thread->cond, 0);
  thread->current_timer = 0;
  thread->captured = pthread_self ();
  thread->clock_id = clock_id;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct thread_node* thread_links2ptr ( struct list_links list) [static, read]

Definition at line 131 of file timer_routines.c.

{
  return (struct thread_node *) ((char *) list
                             - offsetof (struct thread_node, links));
}

Here is the caller graph for this function:

static struct timer_node* timer_links2ptr ( struct list_links list) [static, read]

Definition at line 138 of file timer_routines.c.

{
  return (struct timer_node *) ((char *) list
                            - offsetof (struct timer_node, links));
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 52 of file timer_routines.c.

Definition at line 49 of file timer_routines.c.

Definition at line 46 of file timer_routines.c.

struct thread_node[THREAD_MAXNODES] [static]

Definition at line 40 of file timer_routines.c.