⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer_routines.c

📁 glibc 2.9,最新版的C语言库函数
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Helper code for POSIX timer implementation on NPTL.   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.   This file is part of the GNU C Library.   Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public License as   published by the Free Software Foundation; either version 2.1 of the   License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; see the file COPYING.LIB.  If not,   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA.  */#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>/* Number of threads used.  */#define THREAD_MAXNODES	16/* Array containing the descriptors for the used threads.  */static struct thread_node thread_array[THREAD_MAXNODES];/* Static array with the structures for all the timers.  */struct timer_node __timer_array[TIMER_MAX];/* Global lock to protect operation on the lists.  */pthread_mutex_t __timer_mutex = PTHREAD_MUTEX_INITIALIZER;/* Variable to protext initialization.  */pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT;/* Nonzero if initialization of timer implementation failed.  */int __timer_init_failed;/* Node for the thread used to deliver signals.  */struct thread_node __timer_signal_thread_rclk;/* Lists to keep free and used timers and threads.  */struct list_links timer_free_list;struct list_links thread_free_list;struct list_links thread_active_list;#ifdef __NR_rt_sigqueueinfoextern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *);#endif/* List handling functions.  */static inline voidlist_init (struct list_links *list){  list->next = list->prev = list;}static inline voidlist_append (struct list_links *list, struct list_links *newp){  newp->prev = list->prev;  newp->next = list;  list->prev->next = newp;  list->prev = newp;}static inline voidlist_insbefore (struct list_links *list, struct list_links *newp){  list_append (list, newp);}/* * Like list_unlink_ip, except that calling it on a node that * is already unlinked is disastrous rather than a noop. */static inline voidlist_unlink (struct list_links *list){  struct list_links *lnext = list->next, *lprev = list->prev;  lnext->prev = lprev;  lprev->next = lnext;}static inline struct list_links *list_first (struct list_links *list){  return list->next;}static inline struct list_links *list_null (struct list_links *list){  return list;}static inline struct list_links *list_next (struct list_links *list){  return list->next;}static inline intlist_isempty (struct list_links *list){  return list->next == list;}/* Functions build on top of the list functions.  */static inline struct thread_node *thread_links2ptr (struct list_links *list){  return (struct thread_node *) ((char *) list				 - offsetof (struct thread_node, links));}static inline struct timer_node *timer_links2ptr (struct list_links *list){  return (struct timer_node *) ((char *) list				- offsetof (struct timer_node, links));}/* Initialize a newly allocated thread structure.  */static voidthread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id){  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;}/* Initialize the global lists, and acquire global resources.  Error   reporting is done by storing a non-zero value to the global variable   timer_init_failed.  */static voidinit_module (void){  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);}/* This is a handler executed in a child process after a fork()   occurs.  It reinitializes the module, resetting all of the data   structures to their initial state.  The mutex is initialized in   case it was locked in the parent process.  */static voidreinit_after_fork (void){  init_module ();  pthread_mutex_init (&__timer_mutex, 0);}/* Called once form pthread_once in timer_init. This initializes the   module and ensures that reinit_after_fork will be executed in any   child process.  */void__timer_init_once (void){  init_module ();  pthread_atfork (0, 0, reinit_after_fork);}/* Deinitialize a thread that is about to be deallocated.  */static voidthread_deinit (struct thread_node *thread){  assert (list_isempty (&thread->timer_queue));  pthread_cond_destroy (&thread->cond);}/* Allocate a thread structure from the global free list.  Global   mutex lock must be held by caller.  The thread is moved to   the active list. */struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id){  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;}/* Return a thread structure to the global free list.  Global lock   must be held by caller.  */void__timer_thread_dealloc (struct thread_node *thread){  thread_deinit (thread);  list_unlink (&thread->links);  list_append (&thread_free_list, &thread->links);}/* Each of our threads which terminates executes this cleanup   handler. We never terminate threads ourselves; if a thread gets here   it means that the evil application has killed it.  If the thread has   timers, these require servicing and so we must hire a replacement   thread right away.  We must also unblock another thread that may   have been waiting for this thread to finish servicing a timer (see   timer_delete()).  */static voidthread_cleanup (void *val){  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);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -