Blame sysdeps/pthread/posix-timer.h

Packit Service 82fcde
/* Definitions for POSIX timer implementation on top of NPTL.
Packit Service 82fcde
   Copyright (C) 2000-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public License as
Packit Service 82fcde
   published by the Free Software Foundation; either version 2.1 of the
Packit Service 82fcde
   License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; see the file COPYING.LIB.  If
Packit Service 82fcde
   not, see <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <limits.h>
Packit Service 82fcde
#include <signal.h>
Packit Service 82fcde
#include <list.h>
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Forward declaration.  */
Packit Service 82fcde
struct timer_node;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Definitions for an internal thread of the POSIX timer implementation.  */
Packit Service 82fcde
struct thread_node
Packit Service 82fcde
{
Packit Service 82fcde
  struct list_head links;
Packit Service 82fcde
  pthread_attr_t attr;
Packit Service 82fcde
  pthread_t id;
Packit Service 82fcde
  unsigned int exists;
Packit Service 82fcde
  struct list_head timer_queue;
Packit Service 82fcde
  pthread_cond_t cond;
Packit Service 82fcde
  struct timer_node *current_timer;
Packit Service 82fcde
  pthread_t captured;
Packit Service 82fcde
  clockid_t clock_id;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Internal representation of a timer.  */
Packit Service 82fcde
struct timer_node
Packit Service 82fcde
{
Packit Service 82fcde
  struct list_head links;
Packit Service 82fcde
  struct sigevent event;
Packit Service 82fcde
  clockid_t clock;
Packit Service 82fcde
  struct itimerspec value;
Packit Service 82fcde
  struct timespec expirytime;
Packit Service 82fcde
  pthread_attr_t attr;
Packit Service 82fcde
  unsigned int abstime;
Packit Service 82fcde
  unsigned int armed;
Packit Service 82fcde
  enum {
Packit Service 82fcde
    TIMER_FREE, TIMER_INUSE, TIMER_DELETED
Packit Service 82fcde
  } inuse;
Packit Service 82fcde
  struct thread_node *thread;
Packit Service 82fcde
  pid_t creator_pid;
Packit Service 82fcde
  int refcount;
Packit Service 82fcde
  int overrun_count;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* The limit is not published if we are compiled with kernel timer support.
Packit Service 82fcde
   But we still compiled in this implementation with its limit unless built
Packit Service 82fcde
   to require the kernel support.  */
Packit Service 82fcde
#ifndef TIMER_MAX
Packit Service 82fcde
# define TIMER_MAX 256
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Static array with the structures for all the timers.  */
Packit Service 82fcde
extern struct timer_node __timer_array[TIMER_MAX];
Packit Service 82fcde
Packit Service 82fcde
/* Global lock to protect operation on the lists.  */
Packit Service 82fcde
extern pthread_mutex_t __timer_mutex;
Packit Service 82fcde
Packit Service 82fcde
/* Variable to protext initialization.  */
Packit Service 82fcde
extern pthread_once_t __timer_init_once_control;
Packit Service 82fcde
Packit Service 82fcde
/* Nonzero if initialization of timer implementation failed.  */
Packit Service 82fcde
extern int __timer_init_failed;
Packit Service 82fcde
Packit Service 82fcde
/* Node for the thread used to deliver signals.  */
Packit Service 82fcde
extern struct thread_node __timer_signal_thread_rclk;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Return pointer to timer structure corresponding to ID.  */
Packit Service 82fcde
#define timer_id2ptr(timerid) ((struct timer_node *) timerid)
Packit Service 82fcde
#define timer_ptr2id(timerid) ((timer_t) timerid)
Packit Service 82fcde
Packit Service 82fcde
/* Check whether timer is valid; global mutex must be held. */
Packit Service 82fcde
static inline int
Packit Service 82fcde
timer_valid (struct timer_node *timer)
Packit Service 82fcde
{
Packit Service 82fcde
  return timer && timer->inuse == TIMER_INUSE;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Timer refcount functions; need global mutex. */
Packit Service 82fcde
extern void __timer_dealloc (struct timer_node *timer);
Packit Service 82fcde
Packit Service 82fcde
static inline void
Packit Service 82fcde
timer_addref (struct timer_node *timer)
Packit Service 82fcde
{
Packit Service 82fcde
  timer->refcount++;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static inline void
Packit Service 82fcde
timer_delref (struct timer_node *timer)
Packit Service 82fcde
{
Packit Service 82fcde
  if (--timer->refcount == 0)
Packit Service 82fcde
    __timer_dealloc (timer);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Timespec helper routines.  */
Packit Service 82fcde
static inline int
Packit Service 82fcde
__attribute ((always_inline))
Packit Service 82fcde
timespec_compare (const struct timespec *left, const struct timespec *right)
Packit Service 82fcde
{
Packit Service 82fcde
  if (left->tv_sec < right->tv_sec)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
  if (left->tv_sec > right->tv_sec)
Packit Service 82fcde
    return 1;
Packit Service 82fcde
Packit Service 82fcde
  if (left->tv_nsec < right->tv_nsec)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
  if (left->tv_nsec > right->tv_nsec)
Packit Service 82fcde
    return 1;
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static inline void
Packit Service 82fcde
timespec_add (struct timespec *sum, const struct timespec *left,
Packit Service 82fcde
	      const struct timespec *right)
Packit Service 82fcde
{
Packit Service 82fcde
  sum->tv_sec = left->tv_sec + right->tv_sec;
Packit Service 82fcde
  sum->tv_nsec = left->tv_nsec + right->tv_nsec;
Packit Service 82fcde
Packit Service 82fcde
  if (sum->tv_nsec >= 1000000000)
Packit Service 82fcde
    {
Packit Service 82fcde
      ++sum->tv_sec;
Packit Service 82fcde
      sum->tv_nsec -= 1000000000;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static inline void
Packit Service 82fcde
timespec_sub (struct timespec *diff, const struct timespec *left,
Packit Service 82fcde
	      const struct timespec *right)
Packit Service 82fcde
{
Packit Service 82fcde
  diff->tv_sec = left->tv_sec - right->tv_sec;
Packit Service 82fcde
  diff->tv_nsec = left->tv_nsec - right->tv_nsec;
Packit Service 82fcde
Packit Service 82fcde
  if (diff->tv_nsec < 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      --diff->tv_sec;
Packit Service 82fcde
      diff->tv_nsec += 1000000000;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* We need one of the list functions in the other modules.  */
Packit Service 82fcde
static inline void
Packit Service 82fcde
list_unlink_ip (struct list_head *list)
Packit Service 82fcde
{
Packit Service 82fcde
  struct list_head *lnext = list->next, *lprev = list->prev;
Packit Service 82fcde
Packit Service 82fcde
  lnext->prev = lprev;
Packit Service 82fcde
  lprev->next = lnext;
Packit Service 82fcde
Packit Service 82fcde
  /* The suffix ip means idempotent; list_unlink_ip can be called
Packit Service 82fcde
   * two or more times on the same node.
Packit Service 82fcde
   */
Packit Service 82fcde
Packit Service 82fcde
  list->next = list;
Packit Service 82fcde
  list->prev = list;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Functions in the helper file.  */
Packit Service 82fcde
extern void __timer_mutex_cancel_handler (void *arg);
Packit Service 82fcde
extern void __timer_init_once (void);
Packit Service 82fcde
extern struct timer_node *__timer_alloc (void);
Packit Service 82fcde
extern int __timer_thread_start (struct thread_node *thread);
Packit Service 82fcde
extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t);
Packit Service 82fcde
extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t);
Packit Service 82fcde
extern void __timer_thread_dealloc (struct thread_node *thread);
Packit Service 82fcde
extern int __timer_thread_queue_timer (struct thread_node *thread,
Packit Service 82fcde
				       struct timer_node *insert);
Packit Service 82fcde
extern void __timer_thread_wakeup (struct thread_node *thread);