thread.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:16k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* Thread management routine
  2.  * Copyright (C) 1998, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
  3.  *
  4.  * This file is part of GNU Zebra.
  5.  *
  6.  * GNU Zebra is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation; either version 2, or (at your option) any
  9.  * later version.
  10.  *
  11.  * GNU Zebra is distributed in the hope that it will be useful, but
  12.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
  18.  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19.  * 02111-1307, USA.  
  20.  */
  21. /* #define DEBUG */
  22. #include <zebra.h>
  23. #include "thread.h"
  24. #include "memory.h"
  25. #include "log.h"
  26. /* Struct timeval's tv_usec one second value.  */
  27. #define TIMER_SECOND_MICRO 1000000L
  28. struct timeval
  29. timeval_adjust (struct timeval a)
  30. {
  31.   while (a.tv_usec >= TIMER_SECOND_MICRO)
  32.     {
  33.       a.tv_usec -= TIMER_SECOND_MICRO;
  34.       a.tv_sec++;
  35.     }
  36.   while (a.tv_usec < 0)
  37.     {
  38.       a.tv_usec += TIMER_SECOND_MICRO;
  39.       a.tv_sec--;
  40.     }
  41.   if (a.tv_sec < 0)
  42.     {
  43.       a.tv_sec = 0;
  44.       a.tv_usec = 10;
  45.     }
  46.   if (a.tv_sec > TIMER_SECOND_MICRO)
  47.     a.tv_sec = TIMER_SECOND_MICRO;    
  48.   return a;
  49. }
  50. static struct timeval
  51. timeval_subtract (struct timeval a, struct timeval b)
  52. {
  53.   struct timeval ret;
  54.   ret.tv_usec = a.tv_usec - b.tv_usec;
  55.   ret.tv_sec = a.tv_sec - b.tv_sec;
  56.   return timeval_adjust (ret);
  57. }
  58. static int
  59. timeval_cmp (struct timeval a, struct timeval b)
  60. {
  61.   return (a.tv_sec == b.tv_sec
  62.   ? a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);
  63. }
  64. static unsigned long
  65. timeval_elapsed (struct timeval a, struct timeval b)
  66. {
  67.   return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO)
  68.   + (a.tv_usec - b.tv_usec));
  69. }
  70. /* List allocation and head/tail print out. */
  71. static void
  72. thread_list_debug (struct thread_list *list)
  73. {
  74.   printf ("count [%d] head [%p] tail [%p]n",
  75.   list->count, list->head, list->tail);
  76. }
  77. /* Debug print for thread_master. */
  78. void
  79. thread_master_debug (struct thread_master *m)
  80. {
  81.   printf ("-----------n");
  82.   printf ("readlist  : ");
  83.   thread_list_debug (&m->read);
  84.   printf ("writelist : ");
  85.   thread_list_debug (&m->write);
  86.   printf ("timerlist : ");
  87.   thread_list_debug (&m->timer);
  88.   printf ("eventlist : ");
  89.   thread_list_debug (&m->event);
  90.   printf ("unuselist : ");
  91.   thread_list_debug (&m->unuse);
  92.   printf ("total alloc: [%ld]n", m->alloc);
  93.   printf ("-----------n");
  94. }
  95. /* Allocate new thread master.  */
  96. struct thread_master *
  97. thread_master_create ()
  98. {
  99.   return (struct thread_master *) XCALLOC (MTYPE_THREAD_MASTER,
  100.    sizeof (struct thread_master));
  101. }
  102. /* Add a new thread to the list.  */
  103. static void
  104. thread_list_add (struct thread_list *list, struct thread *thread)
  105. {
  106.   thread->next = NULL;
  107.   thread->prev = list->tail;
  108.   if (list->tail)
  109.     list->tail->next = thread;
  110.   else
  111.     list->head = thread;
  112.   list->tail = thread;
  113.   list->count++;
  114. }
  115. /* Add a new thread just before the point.  */
  116. static void
  117. thread_list_add_before (struct thread_list *list, 
  118. struct thread *point, 
  119. struct thread *thread)
  120. {
  121.   thread->next = point;
  122.   thread->prev = point->prev;
  123.   if (point->prev)
  124.     point->prev->next = thread;
  125.   else
  126.     list->head = thread;
  127.   point->prev = thread;
  128.   list->count++;
  129. }
  130. /* Delete a thread from the list. */
  131. static struct thread *
  132. thread_list_delete (struct thread_list *list, struct thread *thread)
  133. {
  134.   if (thread->next)
  135.     thread->next->prev = thread->prev;
  136.   else
  137.     list->tail = thread->prev;
  138.   if (thread->prev)
  139.     thread->prev->next = thread->next;
  140.   else
  141.     list->head = thread->next;
  142.   thread->next = thread->prev = NULL;
  143.   list->count--;
  144.   return thread;
  145. }
  146. /* Move thread to unuse list. */
  147. static void
  148. thread_add_unuse (struct thread_master *m, struct thread *thread)
  149. {
  150.   assert (m != NULL);
  151.   assert (thread->next == NULL);
  152.   assert (thread->prev == NULL);
  153.   assert (thread->type == THREAD_UNUSED);
  154.   thread_list_add (&m->unuse, thread);
  155. }
  156. /* Free all unused thread. */
  157. static void
  158. thread_list_free (struct thread_master *m, struct thread_list *list)
  159. {
  160.   struct thread *t;
  161.   struct thread *next;
  162.   for (t = list->head; t; t = next)
  163.     {
  164.       next = t->next;
  165.       XFREE (MTYPE_THREAD, t);
  166.       list->count--;
  167.       m->alloc--;
  168.     }
  169. }
  170. /* Stop thread scheduler. */
  171. void
  172. thread_master_free (struct thread_master *m)
  173. {
  174.   thread_list_free (m, &m->read);
  175.   thread_list_free (m, &m->write);
  176.   thread_list_free (m, &m->timer);
  177.   thread_list_free (m, &m->event);
  178.   thread_list_free (m, &m->ready);
  179.   thread_list_free (m, &m->unuse);
  180.   XFREE (MTYPE_THREAD_MASTER, m);
  181. }
  182. /* Delete top of the list and return it. */
  183. static struct thread *
  184. thread_trim_head (struct thread_list *list)
  185. {
  186.   if (list->head)
  187.     return thread_list_delete (list, list->head);
  188.   return NULL;
  189. }
  190. /* Thread list is empty or not.  */
  191. int
  192. thread_empty (struct thread_list *list)
  193. {
  194.   return  list->head ? 0 : 1;
  195. }
  196. /* Return remain time. */
  197. char *
  198. thread_timer_remain_second (struct thread *thread)
  199. {
  200.   struct timeval timer_now;
  201.   struct tm *tm;
  202.   time_t remain_time;
  203.   char buf[25];
  204.   int len = 25;
  205.   gettimeofday (&timer_now, NULL);
  206.   remain_time = thread->u.sands.tv_sec - timer_now.tv_sec;
  207.   if (remain_time < 0)
  208.     remain_time = 0;
  209.   tm = gmtime (&remain_time);
  210.   /* Making formatted timer strings. */
  211. #define ONE_DAY_SECOND 60*60*24
  212. #define ONE_WEEK_SECOND 60*60*24*7
  213.   if (remain_time < ONE_DAY_SECOND)
  214.     snprintf (buf, len, "%02d:%02d:%02d",
  215.               tm->tm_hour, tm->tm_min, tm->tm_sec);
  216.   else if (remain_time < ONE_WEEK_SECOND)
  217.     snprintf (buf, len, "%dd%02dh%02dm",
  218.               tm->tm_yday, tm->tm_hour, tm->tm_min);
  219.   else
  220.     snprintf (buf, len, "%02dw%dd%02dh",
  221.               tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
  222.   return buf;
  223. }
  224. /* Get new thread.  */
  225. static struct thread *
  226. thread_get (struct thread_master *m, u_char type,
  227.     int (*func) (struct thread *), void *arg)
  228. {
  229.   struct thread *thread;
  230.   if (m->unuse.head)
  231.     thread = thread_trim_head (&m->unuse);
  232.   else
  233.     {
  234.       thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread));
  235.       m->alloc++;
  236.     }
  237.   thread->type = type;
  238.   thread->master = m;
  239.   thread->func = func;
  240.   thread->arg = arg;
  241.   
  242.   return thread;
  243. }
  244. /* Add new read thread. */
  245. struct thread *
  246. thread_add_read (struct thread_master *m, 
  247.  int (*func) (struct thread *), void *arg, int fd)
  248. {
  249.   struct thread *thread;
  250.   assert (m != NULL);
  251.   if (FD_ISSET (fd, &m->readfd))
  252.     {
  253.       zlog (NULL, LOG_WARNING, "There is already read fd [%d]", fd);
  254.       return NULL;
  255.     }
  256.   thread = thread_get (m, THREAD_READ, func, arg);
  257.   FD_SET (fd, &m->readfd);
  258.   thread->u.fd = fd;
  259.   thread_list_add (&m->read, thread);
  260.   return thread;
  261. }
  262. /* Add new write thread. */
  263. struct thread *
  264. thread_add_write (struct thread_master *m,
  265.  int (*func) (struct thread *), void *arg, int fd)
  266. {
  267.   struct thread *thread;
  268.   assert (m != NULL);
  269.   if (FD_ISSET (fd, &m->writefd))
  270.     {
  271.       zlog (NULL, LOG_WARNING, "There is already write fd [%d]", fd);
  272.       return NULL;
  273.     }
  274.   thread = thread_get (m, THREAD_WRITE, func, arg);
  275.   FD_SET (fd, &m->writefd);
  276.   thread->u.fd = fd;
  277.   thread_list_add (&m->write, thread);
  278.   return thread;
  279. }
  280. /* Add timer event thread. */
  281. struct thread *
  282. thread_add_timer (struct thread_master *m,
  283.   int (*func) (struct thread *), void *arg, long timer)
  284. {
  285.   struct timeval timer_now;
  286.   struct thread *thread;
  287. #ifndef TIMER_NO_SORT
  288.   struct thread *tt;
  289. #endif /* TIMER_NO_SORT */
  290.   assert (m != NULL);
  291.   thread = thread_get (m, THREAD_TIMER, func, arg);
  292.   /* Do we need jitter here? */
  293.   gettimeofday (&timer_now, NULL);
  294.   timer_now.tv_sec += timer;
  295.   thread->u.sands = timer_now;
  296.   /* Sort by timeval. */
  297. #ifdef TIMER_NO_SORT
  298.   thread_list_add (&m->timer, thread);
  299. #else
  300.   for (tt = m->timer.head; tt; tt = tt->next)
  301.     if (timeval_cmp (thread->u.sands, tt->u.sands) <= 0)
  302.       break;
  303.   if (tt)
  304.     thread_list_add_before (&m->timer, tt, thread);
  305.   else
  306.     thread_list_add (&m->timer, thread);
  307. #endif /* TIMER_NO_SORT */
  308.   return thread;
  309. }
  310. /* Add simple event thread. */
  311. struct thread *
  312. thread_add_event (struct thread_master *m,
  313.   int (*func) (struct thread *), void *arg, int val)
  314. {
  315.   struct thread *thread;
  316.   assert (m != NULL);
  317.   thread = thread_get (m, THREAD_EVENT, func, arg);
  318.   thread->u.val = val;
  319.   thread_list_add (&m->event, thread);
  320.   return thread;
  321. }
  322. /* Cancel thread from scheduler. */
  323. void
  324. thread_cancel (struct thread *thread)
  325. {
  326.   switch (thread->type)
  327.     {
  328.     case THREAD_READ:
  329.       assert (FD_ISSET (thread->u.fd, &thread->master->readfd));
  330.       FD_CLR (thread->u.fd, &thread->master->readfd);
  331.       thread_list_delete (&thread->master->read, thread);
  332.       break;
  333.     case THREAD_WRITE:
  334.       assert (FD_ISSET (thread->u.fd, &thread->master->writefd));
  335.       FD_CLR (thread->u.fd, &thread->master->writefd);
  336.       thread_list_delete (&thread->master->write, thread);
  337.       break;
  338.     case THREAD_TIMER:
  339.       thread_list_delete (&thread->master->timer, thread);
  340.       break;
  341.     case THREAD_EVENT:
  342.       thread_list_delete (&thread->master->event, thread);
  343.       break;
  344.     case THREAD_READY:
  345.       thread_list_delete (&thread->master->ready, thread);
  346.       break;
  347.     default:
  348.       break;
  349.     }
  350.   thread->type = THREAD_UNUSED;
  351.   thread_add_unuse (thread->master, thread);
  352. }
  353. /* Delete all events which has argument value arg. */
  354. void
  355. thread_cancel_event (struct thread_master *m, void *arg)
  356. {
  357.   struct thread *thread;
  358.   thread = m->event.head;
  359.   while (thread)
  360.     {
  361.       struct thread *t;
  362.       t = thread;
  363.       thread = t->next;
  364.       if (t->arg == arg)
  365. {
  366.   thread_list_delete (&m->event, t);
  367.   t->type = THREAD_UNUSED;
  368.   thread_add_unuse (m, t);
  369. }
  370.     }
  371. }
  372. #ifdef TIMER_NO_SORT
  373. struct timeval *
  374. thread_timer_wait (struct thread_master *m, struct timeval *timer_val)
  375. {
  376.   struct timeval timer_now;
  377.   struct timeval timer_min;
  378.   struct timeval *timer_wait;
  379.   gettimeofday (&timer_now, NULL);
  380.   timer_wait = NULL;
  381.   for (thread = m->timer.head; thread; thread = thread->next)
  382.     {
  383.       if (! timer_wait)
  384. timer_wait = &thread->u.sands;
  385.       else if (timeval_cmp (thread->u.sands, *timer_wait) < 0)
  386. timer_wait = &thread->u.sands;
  387.     }
  388.   if (m->timer.head)
  389.     {
  390.       timer_min = *timer_wait;
  391.       timer_min = timeval_subtract (timer_min, timer_now);
  392.       if (timer_min.tv_sec < 0)
  393. {
  394.   timer_min.tv_sec = 0;
  395.   timer_min.tv_usec = 10;
  396. }
  397.       timer_wait = &timer_min;
  398.     }
  399.   else
  400.     timer_wait = NULL;
  401.   if (timer_wait)
  402.     {
  403.       *timer_val = timer_wait;
  404.       return timer_val;
  405.     }
  406.   return NULL;
  407. }
  408. #else /* ! TIMER_NO_SORT */
  409. struct timeval *
  410. thread_timer_wait (struct thread_master *m, struct timeval *timer_val)
  411. {
  412.   struct timeval timer_now;
  413.   struct timeval timer_min;
  414.   if (m->timer.head)
  415.     {
  416.       gettimeofday (&timer_now, NULL);
  417.       timer_min = m->timer.head->u.sands;
  418.       timer_min = timeval_subtract (timer_min, timer_now);
  419.       if (timer_min.tv_sec < 0)
  420. {
  421.   timer_min.tv_sec = 0;
  422.   timer_min.tv_usec = 10;
  423. }
  424.       *timer_val = timer_min;
  425.       return timer_val;
  426.     }
  427.   return NULL;
  428. }
  429. #endif /* TIMER_NO_SORT */
  430. struct thread *
  431. thread_run (struct thread_master *m, struct thread *thread,
  432.     struct thread *fetch)
  433. {
  434.   *fetch = *thread;
  435.   thread->type = THREAD_UNUSED;
  436.   thread_add_unuse (m, thread);
  437.   return fetch;
  438. }
  439. int
  440. thread_process_fd (struct thread_master *m, struct thread_list *list,
  441.    fd_set *fdset, fd_set *mfdset)
  442. {
  443.   struct thread *thread;
  444.   struct thread *next;
  445.   int ready = 0;
  446.   for (thread = list->head; thread; thread = next)
  447.     {
  448.       next = thread->next;
  449.       if (FD_ISSET (THREAD_FD (thread), fdset))
  450. {
  451.   assert (FD_ISSET (THREAD_FD (thread), mfdset));
  452.   FD_CLR(THREAD_FD (thread), mfdset);
  453.   thread_list_delete (list, thread);
  454.   thread_list_add (&m->ready, thread);
  455.   thread->type = THREAD_READY;
  456.   ready++;
  457. }
  458.     }
  459.   return ready;
  460. }
  461. /* Fetch next ready thread. */
  462. struct thread *
  463. thread_fetch (struct thread_master *m, struct thread *fetch)
  464. {
  465.   int num;
  466.   int ready;
  467.   struct thread *thread;
  468.   fd_set readfd;
  469.   fd_set writefd;
  470.   fd_set exceptfd;
  471.   struct timeval timer_now;
  472.   struct timeval timer_val;
  473.   struct timeval *timer_wait;
  474.   struct timeval timer_nowait;
  475.   timer_nowait.tv_sec = 0;
  476.   timer_nowait.tv_usec = 0;
  477.   while (1)
  478.     {
  479.       /* Normal event is the highest priority.  */
  480.       if ((thread = thread_trim_head (&m->event)) != NULL)
  481. return thread_run (m, thread, fetch);
  482.       /* Execute timer.  */
  483.       gettimeofday (&timer_now, NULL);
  484.       for (thread = m->timer.head; thread; thread = thread->next)
  485. if (timeval_cmp (timer_now, thread->u.sands) >= 0)
  486.   {
  487.     thread_list_delete (&m->timer, thread);
  488.     return thread_run (m, thread, fetch);
  489.   }
  490.       /* If there are any ready threads, process top of them.  */
  491.       if ((thread = thread_trim_head (&m->ready)) != NULL)
  492. return thread_run (m, thread, fetch);
  493.       /* Structure copy.  */
  494.       readfd = m->readfd;
  495.       writefd = m->writefd;
  496.       exceptfd = m->exceptfd;
  497.       /* Calculate select wait timer. */
  498.       timer_wait = thread_timer_wait (m, &timer_val);
  499.       num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
  500.       if (num == 0)
  501. continue;
  502.       if (num < 0)
  503. {
  504.   if (errno == EINTR)
  505.     continue;
  506.   zlog_warn ("select() error: %s", strerror (errno));
  507.   return NULL;
  508. }
  509.       /* Normal priority read thead. */
  510.       ready = thread_process_fd (m, &m->read, &readfd, &m->readfd);
  511.       /* Write thead. */
  512.       ready = thread_process_fd (m, &m->write, &writefd, &m->writefd);
  513.       if ((thread = thread_trim_head (&m->ready)) != NULL)
  514. return thread_run (m, thread, fetch);
  515.     }
  516. }
  517. static unsigned long
  518. thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start)
  519. {
  520.   unsigned long thread_time;
  521. #ifdef HAVE_RUSAGE
  522.   /* This is 'user + sys' time.  */
  523.   thread_time = timeval_elapsed (now->ru_utime, start->ru_utime);
  524.   thread_time += timeval_elapsed (now->ru_stime, start->ru_stime);
  525. #else
  526.   /* When rusage is not available, simple elapsed time is used.  */
  527.   thread_time = timeval_elapsed (*now, *start);
  528. #endif /* HAVE_RUSAGE */
  529.   return thread_time;
  530. }
  531. /* We should aim to yield after THREAD_YIELD_TIME_SLOT
  532.    milliseconds.  */
  533. int
  534. thread_should_yield (struct thread *thread)
  535. {
  536.   RUSAGE_T ru;
  537.   GETRUSAGE (&ru);
  538.   if (thread_consumed_time (&ru, &thread->ru) > THREAD_YIELD_TIME_SLOT)
  539.     return 1;
  540.   else
  541.     return 0;
  542. }
  543. /* We check thread consumed time. If the system has getrusage, we'll
  544.    use that to get indepth stats on the performance of the thread.  If
  545.    not - we'll use gettimeofday for some guestimation.  */
  546. void
  547. thread_call (struct thread *thread)
  548. {
  549.   unsigned long thread_time;
  550.   RUSAGE_T ru;
  551.   GETRUSAGE (&thread->ru);
  552.   (*thread->func) (thread);
  553.   GETRUSAGE (&ru);
  554.   thread_time = thread_consumed_time (&ru, &thread->ru);
  555. #ifdef THREAD_CONSUMED_TIME_CHECK
  556.   if (thread_time > 200000L)
  557.     {
  558.       /*
  559.        * We have a CPU Hog on our hands.
  560.        * Whinge about it now, so we're aware this is yet another task
  561.        * to fix.
  562.        */
  563.       zlog_err ("CPU HOG task %lx ran for %ldms",
  564.                 /* FIXME: report the name of the function somehow */
  565. (unsigned long) thread->func,
  566. thread_time / 1000L);
  567.     }
  568. #endif /* THREAD_CONSUMED_TIME_CHECK */
  569. }
  570. /* Execute thread */
  571. struct thread *
  572. thread_execute (struct thread_master *m,
  573.                 int (*func)(struct thread *), 
  574.                 void *arg,
  575.                 int val)
  576. {
  577.   struct thread dummy; 
  578.   memset (&dummy, 0, sizeof (struct thread));
  579.   dummy.type = THREAD_EVENT;
  580.   dummy.master = NULL;
  581.   dummy.func = func;
  582.   dummy.arg = arg;
  583.   dummy.u.val = val;
  584.   thread_call (&dummy);
  585.   return NULL;
  586. }