File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / lib / thread.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:12 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    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: 
   22: /* #define DEBUG */
   23: 
   24: #include <zebra.h>
   25: 
   26: #include "thread.h"
   27: #include "memory.h"
   28: #include "log.h"
   29: #include "hash.h"
   30: #include "command.h"
   31: #include "sigevent.h"
   32: 
   33: /* Recent absolute time of day */
   34: struct timeval recent_time;
   35: static struct timeval last_recent_time;
   36: /* Relative time, since startup */
   37: static struct timeval relative_time;
   38: static struct timeval relative_time_base;
   39: /* init flag */
   40: static unsigned short timers_inited;
   41: 
   42: static struct hash *cpu_record = NULL;
   43: 
   44: /* Struct timeval's tv_usec one second value.  */
   45: #define TIMER_SECOND_MICRO 1000000L
   46: 
   47: /* Adjust so that tv_usec is in the range [0,TIMER_SECOND_MICRO).
   48:    And change negative values to 0. */
   49: static struct timeval
   50: timeval_adjust (struct timeval a)
   51: {
   52:   while (a.tv_usec >= TIMER_SECOND_MICRO)
   53:     {
   54:       a.tv_usec -= TIMER_SECOND_MICRO;
   55:       a.tv_sec++;
   56:     }
   57: 
   58:   while (a.tv_usec < 0)
   59:     {
   60:       a.tv_usec += TIMER_SECOND_MICRO;
   61:       a.tv_sec--;
   62:     }
   63: 
   64:   if (a.tv_sec < 0)
   65:       /* Change negative timeouts to 0. */
   66:       a.tv_sec = a.tv_usec = 0;
   67: 
   68:   return a;
   69: }
   70: 
   71: static struct timeval
   72: timeval_subtract (struct timeval a, struct timeval b)
   73: {
   74:   struct timeval ret;
   75: 
   76:   ret.tv_usec = a.tv_usec - b.tv_usec;
   77:   ret.tv_sec = a.tv_sec - b.tv_sec;
   78: 
   79:   return timeval_adjust (ret);
   80: }
   81: 
   82: static long
   83: timeval_cmp (struct timeval a, struct timeval b)
   84: {
   85:   return (a.tv_sec == b.tv_sec
   86: 	  ? a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);
   87: }
   88: 
   89: static unsigned long
   90: timeval_elapsed (struct timeval a, struct timeval b)
   91: {
   92:   return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO)
   93: 	  + (a.tv_usec - b.tv_usec));
   94: }
   95: 
   96: #ifndef HAVE_CLOCK_MONOTONIC
   97: static void
   98: quagga_gettimeofday_relative_adjust (void)
   99: {
  100:   struct timeval diff;
  101:   if (timeval_cmp (recent_time, last_recent_time) < 0)
  102:     {
  103:       relative_time.tv_sec++;
  104:       relative_time.tv_usec = 0;
  105:     }
  106:   else
  107:     {
  108:       diff = timeval_subtract (recent_time, last_recent_time);
  109:       relative_time.tv_sec += diff.tv_sec;
  110:       relative_time.tv_usec += diff.tv_usec;
  111:       relative_time = timeval_adjust (relative_time);
  112:     }
  113:   last_recent_time = recent_time;
  114: }
  115: #endif /* !HAVE_CLOCK_MONOTONIC */
  116: 
  117: /* gettimeofday wrapper, to keep recent_time updated */
  118: static int
  119: quagga_gettimeofday (struct timeval *tv)
  120: {
  121:   int ret;
  122:   
  123:   assert (tv);
  124:   
  125:   if (!(ret = gettimeofday (&recent_time, NULL)))
  126:     {
  127:       /* init... */
  128:       if (!timers_inited)
  129:         {
  130:           relative_time_base = last_recent_time = recent_time;
  131:           timers_inited = 1;
  132:         }
  133:       /* avoid copy if user passed recent_time pointer.. */
  134:       if (tv != &recent_time)
  135:         *tv = recent_time;
  136:       return 0;
  137:     }
  138:   return ret;
  139: }
  140: 
  141: static int
  142: quagga_get_relative (struct timeval *tv)
  143: {
  144:   int ret;
  145: 
  146: #ifdef HAVE_CLOCK_MONOTONIC
  147:   {
  148:     struct timespec tp;
  149:     if (!(ret = clock_gettime (CLOCK_MONOTONIC, &tp)))
  150:       {
  151:         relative_time.tv_sec = tp.tv_sec;
  152:         relative_time.tv_usec = tp.tv_nsec / 1000;
  153:       }
  154:   }
  155: #else /* !HAVE_CLOCK_MONOTONIC */
  156:   if (!(ret = quagga_gettimeofday (&recent_time)))
  157:     quagga_gettimeofday_relative_adjust();
  158: #endif /* HAVE_CLOCK_MONOTONIC */
  159: 
  160:   if (tv)
  161:     *tv = relative_time;
  162: 
  163:   return ret;
  164: }
  165: 
  166: /* Get absolute time stamp, but in terms of the internal timer
  167:  * Could be wrong, but at least won't go back.
  168:  */
  169: static void
  170: quagga_real_stabilised (struct timeval *tv)
  171: {
  172:   *tv = relative_time_base;
  173:   tv->tv_sec += relative_time.tv_sec;
  174:   tv->tv_usec += relative_time.tv_usec;
  175:   *tv = timeval_adjust (*tv);
  176: }
  177: 
  178: /* Exported Quagga timestamp function.
  179:  * Modelled on POSIX clock_gettime.
  180:  */
  181: int
  182: quagga_gettime (enum quagga_clkid clkid, struct timeval *tv)
  183: {
  184:   switch (clkid)
  185:     {
  186:       case QUAGGA_CLK_REALTIME:
  187:         return quagga_gettimeofday (tv);
  188:       case QUAGGA_CLK_MONOTONIC:
  189:         return quagga_get_relative (tv);
  190:       case QUAGGA_CLK_REALTIME_STABILISED:
  191:         quagga_real_stabilised (tv);
  192:         return 0;
  193:       default:
  194:         errno = EINVAL;
  195:         return -1;
  196:     }
  197: }
  198: 
  199: /* time_t value in terms of stabilised absolute time. 
  200:  * replacement for POSIX time()
  201:  */
  202: time_t
  203: quagga_time (time_t *t)
  204: {
  205:   struct timeval tv;
  206:   quagga_real_stabilised (&tv);
  207:   if (t)
  208:     *t = tv.tv_sec;
  209:   return tv.tv_sec;
  210: }
  211: 
  212: /* Public export of recent_relative_time by value */
  213: struct timeval
  214: recent_relative_time (void)
  215: {
  216:   return relative_time;
  217: }
  218: 
  219: static unsigned int
  220: cpu_record_hash_key (struct cpu_thread_history *a)
  221: {
  222:   return (uintptr_t) a->func;
  223: }
  224: 
  225: static int 
  226: cpu_record_hash_cmp (const struct cpu_thread_history *a,
  227: 		     const struct cpu_thread_history *b)
  228: {
  229:   return a->func == b->func;
  230: }
  231: 
  232: static void *
  233: cpu_record_hash_alloc (struct cpu_thread_history *a)
  234: {
  235:   struct cpu_thread_history *new;
  236:   new = XCALLOC (MTYPE_THREAD_STATS, sizeof (struct cpu_thread_history));
  237:   new->func = a->func;
  238:   new->funcname = XSTRDUP(MTYPE_THREAD_FUNCNAME, a->funcname);
  239:   return new;
  240: }
  241: 
  242: static void
  243: cpu_record_hash_free (void *a)
  244: {
  245:   struct cpu_thread_history *hist = a;
  246:  
  247:   XFREE (MTYPE_THREAD_FUNCNAME, hist->funcname);
  248:   XFREE (MTYPE_THREAD_STATS, hist);
  249: }
  250: 
  251: static inline void 
  252: vty_out_cpu_thread_history(struct vty* vty,
  253: 			   struct cpu_thread_history *a)
  254: {
  255: #ifdef HAVE_RUSAGE
  256:   vty_out(vty, "%7ld.%03ld %9d %8ld %9ld %8ld %9ld",
  257: 	  a->cpu.total/1000, a->cpu.total%1000, a->total_calls,
  258: 	  a->cpu.total/a->total_calls, a->cpu.max,
  259: 	  a->real.total/a->total_calls, a->real.max);
  260: #else
  261:   vty_out(vty, "%7ld.%03ld %9d %8ld %9ld",
  262: 	  a->real.total/1000, a->real.total%1000, a->total_calls,
  263: 	  a->real.total/a->total_calls, a->real.max);
  264: #endif
  265:   vty_out(vty, " %c%c%c%c%c%c %s%s",
  266: 	  a->types & (1 << THREAD_READ) ? 'R':' ',
  267: 	  a->types & (1 << THREAD_WRITE) ? 'W':' ',
  268: 	  a->types & (1 << THREAD_TIMER) ? 'T':' ',
  269: 	  a->types & (1 << THREAD_EVENT) ? 'E':' ',
  270: 	  a->types & (1 << THREAD_EXECUTE) ? 'X':' ',
  271: 	  a->types & (1 << THREAD_BACKGROUND) ? 'B' : ' ',
  272: 	  a->funcname, VTY_NEWLINE);
  273: }
  274: 
  275: static void
  276: cpu_record_hash_print(struct hash_backet *bucket, 
  277: 		      void *args[])
  278: {
  279:   struct cpu_thread_history *totals = args[0];
  280:   struct vty *vty = args[1];
  281:   thread_type *filter = args[2];
  282:   struct cpu_thread_history *a = bucket->data;
  283:   
  284:   a = bucket->data;
  285:   if ( !(a->types & *filter) )
  286:        return;
  287:   vty_out_cpu_thread_history(vty,a);
  288:   totals->total_calls += a->total_calls;
  289:   totals->real.total += a->real.total;
  290:   if (totals->real.max < a->real.max)
  291:     totals->real.max = a->real.max;
  292: #ifdef HAVE_RUSAGE
  293:   totals->cpu.total += a->cpu.total;
  294:   if (totals->cpu.max < a->cpu.max)
  295:     totals->cpu.max = a->cpu.max;
  296: #endif
  297: }
  298: 
  299: static void
  300: cpu_record_print(struct vty *vty, thread_type filter)
  301: {
  302:   struct cpu_thread_history tmp;
  303:   void *args[3] = {&tmp, vty, &filter};
  304: 
  305:   memset(&tmp, 0, sizeof tmp);
  306:   tmp.funcname = (char *)"TOTAL";
  307:   tmp.types = filter;
  308: 
  309: #ifdef HAVE_RUSAGE
  310:   vty_out(vty, "%21s %18s %18s%s",
  311:   	  "", "CPU (user+system):", "Real (wall-clock):", VTY_NEWLINE);
  312: #endif
  313:   vty_out(vty, "Runtime(ms)   Invoked Avg uSec Max uSecs");
  314: #ifdef HAVE_RUSAGE
  315:   vty_out(vty, " Avg uSec Max uSecs");
  316: #endif
  317:   vty_out(vty, "  Type  Thread%s", VTY_NEWLINE);
  318:   hash_iterate(cpu_record,
  319: 	       (void(*)(struct hash_backet*,void*))cpu_record_hash_print,
  320: 	       args);
  321: 
  322:   if (tmp.total_calls > 0)
  323:     vty_out_cpu_thread_history(vty, &tmp);
  324: }
  325: 
  326: DEFUN(show_thread_cpu,
  327:       show_thread_cpu_cmd,
  328:       "show thread cpu [FILTER]",
  329:       SHOW_STR
  330:       "Thread information\n"
  331:       "Thread CPU usage\n"
  332:       "Display filter (rwtexb)\n")
  333: {
  334:   int i = 0;
  335:   thread_type filter = (thread_type) -1U;
  336: 
  337:   if (argc > 0)
  338:     {
  339:       filter = 0;
  340:       while (argv[0][i] != '\0')
  341: 	{
  342: 	  switch ( argv[0][i] )
  343: 	    {
  344: 	    case 'r':
  345: 	    case 'R':
  346: 	      filter |= (1 << THREAD_READ);
  347: 	      break;
  348: 	    case 'w':
  349: 	    case 'W':
  350: 	      filter |= (1 << THREAD_WRITE);
  351: 	      break;
  352: 	    case 't':
  353: 	    case 'T':
  354: 	      filter |= (1 << THREAD_TIMER);
  355: 	      break;
  356: 	    case 'e':
  357: 	    case 'E':
  358: 	      filter |= (1 << THREAD_EVENT);
  359: 	      break;
  360: 	    case 'x':
  361: 	    case 'X':
  362: 	      filter |= (1 << THREAD_EXECUTE);
  363: 	      break;
  364: 	    case 'b':
  365: 	    case 'B':
  366: 	      filter |= (1 << THREAD_BACKGROUND);
  367: 	      break;
  368: 	    default:
  369: 	      break;
  370: 	    }
  371: 	  ++i;
  372: 	}
  373:       if (filter == 0)
  374: 	{
  375: 	  vty_out(vty, "Invalid filter \"%s\" specified,"
  376:                   " must contain at least one of 'RWTEXB'%s",
  377: 		  argv[0], VTY_NEWLINE);
  378: 	  return CMD_WARNING;
  379: 	}
  380:     }
  381: 
  382:   cpu_record_print(vty, filter);
  383:   return CMD_SUCCESS;
  384: }
  385: 
  386: static void
  387: cpu_record_hash_clear (struct hash_backet *bucket, 
  388: 		      void *args)
  389: {
  390:   thread_type *filter = args;
  391:   struct cpu_thread_history *a = bucket->data;
  392:   
  393:   a = bucket->data;
  394:   if ( !(a->types & *filter) )
  395:        return;
  396:   
  397:   hash_release (cpu_record, bucket->data);
  398: }
  399: 
  400: static void
  401: cpu_record_clear (thread_type filter)
  402: {
  403:   thread_type *tmp = &filter;
  404:   hash_iterate (cpu_record,
  405: 	        (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
  406: 	        tmp);
  407: }
  408: 
  409: DEFUN(clear_thread_cpu,
  410:       clear_thread_cpu_cmd,
  411:       "clear thread cpu [FILTER]",
  412:       "Clear stored data\n"
  413:       "Thread information\n"
  414:       "Thread CPU usage\n"
  415:       "Display filter (rwtexb)\n")
  416: {
  417:   int i = 0;
  418:   thread_type filter = (thread_type) -1U;
  419: 
  420:   if (argc > 0)
  421:     {
  422:       filter = 0;
  423:       while (argv[0][i] != '\0')
  424: 	{
  425: 	  switch ( argv[0][i] )
  426: 	    {
  427: 	    case 'r':
  428: 	    case 'R':
  429: 	      filter |= (1 << THREAD_READ);
  430: 	      break;
  431: 	    case 'w':
  432: 	    case 'W':
  433: 	      filter |= (1 << THREAD_WRITE);
  434: 	      break;
  435: 	    case 't':
  436: 	    case 'T':
  437: 	      filter |= (1 << THREAD_TIMER);
  438: 	      break;
  439: 	    case 'e':
  440: 	    case 'E':
  441: 	      filter |= (1 << THREAD_EVENT);
  442: 	      break;
  443: 	    case 'x':
  444: 	    case 'X':
  445: 	      filter |= (1 << THREAD_EXECUTE);
  446: 	      break;
  447: 	    case 'b':
  448: 	    case 'B':
  449: 	      filter |= (1 << THREAD_BACKGROUND);
  450: 	      break;
  451: 	    default:
  452: 	      break;
  453: 	    }
  454: 	  ++i;
  455: 	}
  456:       if (filter == 0)
  457: 	{
  458: 	  vty_out(vty, "Invalid filter \"%s\" specified,"
  459:                   " must contain at least one of 'RWTEXB'%s",
  460: 		  argv[0], VTY_NEWLINE);
  461: 	  return CMD_WARNING;
  462: 	}
  463:     }
  464: 
  465:   cpu_record_clear (filter);
  466:   return CMD_SUCCESS;
  467: }
  468: 
  469: /* List allocation and head/tail print out. */
  470: static void
  471: thread_list_debug (struct thread_list *list)
  472: {
  473:   printf ("count [%d] head [%p] tail [%p]\n",
  474: 	  list->count, list->head, list->tail);
  475: }
  476: 
  477: /* Debug print for thread_master. */
  478: static void  __attribute__ ((unused))
  479: thread_master_debug (struct thread_master *m)
  480: {
  481:   printf ("-----------\n");
  482:   printf ("readlist  : ");
  483:   thread_list_debug (&m->read);
  484:   printf ("writelist : ");
  485:   thread_list_debug (&m->write);
  486:   printf ("timerlist : ");
  487:   thread_list_debug (&m->timer);
  488:   printf ("eventlist : ");
  489:   thread_list_debug (&m->event);
  490:   printf ("unuselist : ");
  491:   thread_list_debug (&m->unuse);
  492:   printf ("bgndlist : ");
  493:   thread_list_debug (&m->background);
  494:   printf ("total alloc: [%ld]\n", m->alloc);
  495:   printf ("-----------\n");
  496: }
  497: 
  498: /* Allocate new thread master.  */
  499: struct thread_master *
  500: thread_master_create ()
  501: {
  502:   if (cpu_record == NULL) 
  503:     cpu_record 
  504:       = hash_create_size (1011, (unsigned int (*) (void *))cpu_record_hash_key, 
  505:                           (int (*) (const void *, const void *))cpu_record_hash_cmp);
  506:     
  507:   return (struct thread_master *) XCALLOC (MTYPE_THREAD_MASTER,
  508: 					   sizeof (struct thread_master));
  509: }
  510: 
  511: /* Add a new thread to the list.  */
  512: static void
  513: thread_list_add (struct thread_list *list, struct thread *thread)
  514: {
  515:   thread->next = NULL;
  516:   thread->prev = list->tail;
  517:   if (list->tail)
  518:     list->tail->next = thread;
  519:   else
  520:     list->head = thread;
  521:   list->tail = thread;
  522:   list->count++;
  523: }
  524: 
  525: /* Add a new thread just before the point.  */
  526: static void
  527: thread_list_add_before (struct thread_list *list, 
  528: 			struct thread *point, 
  529: 			struct thread *thread)
  530: {
  531:   thread->next = point;
  532:   thread->prev = point->prev;
  533:   if (point->prev)
  534:     point->prev->next = thread;
  535:   else
  536:     list->head = thread;
  537:   point->prev = thread;
  538:   list->count++;
  539: }
  540: 
  541: /* Delete a thread from the list. */
  542: static struct thread *
  543: thread_list_delete (struct thread_list *list, struct thread *thread)
  544: {
  545:   if (thread->next)
  546:     thread->next->prev = thread->prev;
  547:   else
  548:     list->tail = thread->prev;
  549:   if (thread->prev)
  550:     thread->prev->next = thread->next;
  551:   else
  552:     list->head = thread->next;
  553:   thread->next = thread->prev = NULL;
  554:   list->count--;
  555:   return thread;
  556: }
  557: 
  558: /* Move thread to unuse list. */
  559: static void
  560: thread_add_unuse (struct thread_master *m, struct thread *thread)
  561: {
  562:   assert (m != NULL && thread != NULL);
  563:   assert (thread->next == NULL);
  564:   assert (thread->prev == NULL);
  565:   assert (thread->type == THREAD_UNUSED);
  566:   thread_list_add (&m->unuse, thread);
  567:   /* XXX: Should we deallocate funcname here? */
  568: }
  569: 
  570: /* Free all unused thread. */
  571: static void
  572: thread_list_free (struct thread_master *m, struct thread_list *list)
  573: {
  574:   struct thread *t;
  575:   struct thread *next;
  576: 
  577:   for (t = list->head; t; t = next)
  578:     {
  579:       next = t->next;
  580:       if (t->funcname)
  581:         XFREE (MTYPE_THREAD_FUNCNAME, t->funcname);
  582:       XFREE (MTYPE_THREAD, t);
  583:       list->count--;
  584:       m->alloc--;
  585:     }
  586: }
  587: 
  588: /* Stop thread scheduler. */
  589: void
  590: thread_master_free (struct thread_master *m)
  591: {
  592:   thread_list_free (m, &m->read);
  593:   thread_list_free (m, &m->write);
  594:   thread_list_free (m, &m->timer);
  595:   thread_list_free (m, &m->event);
  596:   thread_list_free (m, &m->ready);
  597:   thread_list_free (m, &m->unuse);
  598:   thread_list_free (m, &m->background);
  599:   
  600:   XFREE (MTYPE_THREAD_MASTER, m);
  601: 
  602:   if (cpu_record)
  603:     {
  604:       hash_clean (cpu_record, cpu_record_hash_free);
  605:       hash_free (cpu_record);
  606:       cpu_record = NULL;
  607:     }
  608: }
  609: 
  610: /* Thread list is empty or not.  */
  611: static inline int
  612: thread_empty (struct thread_list *list)
  613: {
  614:   return  list->head ? 0 : 1;
  615: }
  616: 
  617: /* Delete top of the list and return it. */
  618: static struct thread *
  619: thread_trim_head (struct thread_list *list)
  620: {
  621:   if (!thread_empty (list))
  622:     return thread_list_delete (list, list->head);
  623:   return NULL;
  624: }
  625: 
  626: /* Return remain time in second. */
  627: unsigned long
  628: thread_timer_remain_second (struct thread *thread)
  629: {
  630:   quagga_get_relative (NULL);
  631:   
  632:   if (thread->u.sands.tv_sec - relative_time.tv_sec > 0)
  633:     return thread->u.sands.tv_sec - relative_time.tv_sec;
  634:   else
  635:     return 0;
  636: }
  637: 
  638: /* Trim blankspace and "()"s */
  639: static char *
  640: strip_funcname (const char *funcname) 
  641: {
  642:   char buff[100];
  643:   char tmp, *ret, *e, *b = buff;
  644: 
  645:   strncpy(buff, funcname, sizeof(buff));
  646:   buff[ sizeof(buff) -1] = '\0';
  647:   e = buff +strlen(buff) -1;
  648: 
  649:   /* Wont work for funcname ==  "Word (explanation)"  */
  650: 
  651:   while (*b == ' ' || *b == '(')
  652:     ++b;
  653:   while (*e == ' ' || *e == ')')
  654:     --e;
  655:   e++;
  656: 
  657:   tmp = *e;
  658:   *e = '\0';
  659:   ret  = XSTRDUP (MTYPE_THREAD_FUNCNAME, b);
  660:   *e = tmp;
  661: 
  662:   return ret;
  663: }
  664: 
  665: /* Get new thread.  */
  666: static struct thread *
  667: thread_get (struct thread_master *m, u_char type,
  668: 	    int (*func) (struct thread *), void *arg, const char* funcname)
  669: {
  670:   struct thread *thread;
  671: 
  672:   if (!thread_empty (&m->unuse))
  673:     {
  674:       thread = thread_trim_head (&m->unuse);
  675:       if (thread->funcname)
  676:         XFREE(MTYPE_THREAD_FUNCNAME, thread->funcname);
  677:     }
  678:   else
  679:     {
  680:       thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread));
  681:       m->alloc++;
  682:     }
  683:   thread->type = type;
  684:   thread->add_type = type;
  685:   thread->master = m;
  686:   thread->func = func;
  687:   thread->arg = arg;
  688:   
  689:   thread->funcname = strip_funcname(funcname);
  690: 
  691:   return thread;
  692: }
  693: 
  694: /* Add new read thread. */
  695: struct thread *
  696: funcname_thread_add_read (struct thread_master *m, 
  697: 		 int (*func) (struct thread *), void *arg, int fd, const char* funcname)
  698: {
  699:   struct thread *thread;
  700: 
  701:   assert (m != NULL);
  702: 
  703:   if (FD_ISSET (fd, &m->readfd))
  704:     {
  705:       zlog (NULL, LOG_WARNING, "There is already read fd [%d]", fd);
  706:       return NULL;
  707:     }
  708: 
  709:   thread = thread_get (m, THREAD_READ, func, arg, funcname);
  710:   FD_SET (fd, &m->readfd);
  711:   thread->u.fd = fd;
  712:   thread_list_add (&m->read, thread);
  713: 
  714:   return thread;
  715: }
  716: 
  717: /* Add new write thread. */
  718: struct thread *
  719: funcname_thread_add_write (struct thread_master *m,
  720: 		 int (*func) (struct thread *), void *arg, int fd, const char* funcname)
  721: {
  722:   struct thread *thread;
  723: 
  724:   assert (m != NULL);
  725: 
  726:   if (FD_ISSET (fd, &m->writefd))
  727:     {
  728:       zlog (NULL, LOG_WARNING, "There is already write fd [%d]", fd);
  729:       return NULL;
  730:     }
  731: 
  732:   thread = thread_get (m, THREAD_WRITE, func, arg, funcname);
  733:   FD_SET (fd, &m->writefd);
  734:   thread->u.fd = fd;
  735:   thread_list_add (&m->write, thread);
  736: 
  737:   return thread;
  738: }
  739: 
  740: static struct thread *
  741: funcname_thread_add_timer_timeval (struct thread_master *m,
  742:                                    int (*func) (struct thread *), 
  743:                                   int type,
  744:                                   void *arg, 
  745:                                   struct timeval *time_relative, 
  746:                                   const char* funcname)
  747: {
  748:   struct thread *thread;
  749:   struct thread_list *list;
  750:   struct timeval alarm_time;
  751:   struct thread *tt;
  752: 
  753:   assert (m != NULL);
  754: 
  755:   assert (type == THREAD_TIMER || type == THREAD_BACKGROUND);
  756:   assert (time_relative);
  757:   
  758:   list = ((type == THREAD_TIMER) ? &m->timer : &m->background);
  759:   thread = thread_get (m, type, func, arg, funcname);
  760: 
  761:   /* Do we need jitter here? */
  762:   quagga_get_relative (NULL);
  763:   alarm_time.tv_sec = relative_time.tv_sec + time_relative->tv_sec;
  764:   alarm_time.tv_usec = relative_time.tv_usec + time_relative->tv_usec;
  765:   thread->u.sands = timeval_adjust(alarm_time);
  766: 
  767:   /* Sort by timeval. */
  768:   for (tt = list->head; tt; tt = tt->next)
  769:     if (timeval_cmp (thread->u.sands, tt->u.sands) <= 0)
  770:       break;
  771: 
  772:   if (tt)
  773:     thread_list_add_before (list, tt, thread);
  774:   else
  775:     thread_list_add (list, thread);
  776: 
  777:   return thread;
  778: }
  779: 
  780: 
  781: /* Add timer event thread. */
  782: struct thread *
  783: funcname_thread_add_timer (struct thread_master *m,
  784: 		           int (*func) (struct thread *), 
  785: 		           void *arg, long timer, const char* funcname)
  786: {
  787:   struct timeval trel;
  788: 
  789:   assert (m != NULL);
  790: 
  791:   trel.tv_sec = timer;
  792:   trel.tv_usec = 0;
  793: 
  794:   return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, 
  795:                                             &trel, funcname);
  796: }
  797: 
  798: /* Add timer event thread with "millisecond" resolution */
  799: struct thread *
  800: funcname_thread_add_timer_msec (struct thread_master *m,
  801:                                 int (*func) (struct thread *), 
  802:                                 void *arg, long timer, const char* funcname)
  803: {
  804:   struct timeval trel;
  805: 
  806:   assert (m != NULL);
  807: 
  808:   trel.tv_sec = timer / 1000;
  809:   trel.tv_usec = 1000*(timer % 1000);
  810: 
  811:   return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, 
  812:                                             arg, &trel, funcname);
  813: }
  814: 
  815: /* Add a background thread, with an optional millisec delay */
  816: struct thread *
  817: funcname_thread_add_background (struct thread_master *m,
  818:                                 int (*func) (struct thread *),
  819:                                 void *arg, long delay, 
  820:                                 const char *funcname)
  821: {
  822:   struct timeval trel;
  823:   
  824:   assert (m != NULL);
  825:   
  826:   if (delay)
  827:     {
  828:       trel.tv_sec = delay / 1000;
  829:       trel.tv_usec = 1000*(delay % 1000);
  830:     }
  831:   else
  832:     {
  833:       trel.tv_sec = 0;
  834:       trel.tv_usec = 0;
  835:     }
  836: 
  837:   return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND,
  838:                                             arg, &trel, funcname);
  839: }
  840: 
  841: /* Add simple event thread. */
  842: struct thread *
  843: funcname_thread_add_event (struct thread_master *m,
  844: 		  int (*func) (struct thread *), void *arg, int val, const char* funcname)
  845: {
  846:   struct thread *thread;
  847: 
  848:   assert (m != NULL);
  849: 
  850:   thread = thread_get (m, THREAD_EVENT, func, arg, funcname);
  851:   thread->u.val = val;
  852:   thread_list_add (&m->event, thread);
  853: 
  854:   return thread;
  855: }
  856: 
  857: /* Cancel thread from scheduler. */
  858: void
  859: thread_cancel (struct thread *thread)
  860: {
  861:   struct thread_list *list;
  862:   
  863:   switch (thread->type)
  864:     {
  865:     case THREAD_READ:
  866:       assert (FD_ISSET (thread->u.fd, &thread->master->readfd));
  867:       FD_CLR (thread->u.fd, &thread->master->readfd);
  868:       list = &thread->master->read;
  869:       break;
  870:     case THREAD_WRITE:
  871:       assert (FD_ISSET (thread->u.fd, &thread->master->writefd));
  872:       FD_CLR (thread->u.fd, &thread->master->writefd);
  873:       list = &thread->master->write;
  874:       break;
  875:     case THREAD_TIMER:
  876:       list = &thread->master->timer;
  877:       break;
  878:     case THREAD_EVENT:
  879:       list = &thread->master->event;
  880:       break;
  881:     case THREAD_READY:
  882:       list = &thread->master->ready;
  883:       break;
  884:     case THREAD_BACKGROUND:
  885:       list = &thread->master->background;
  886:       break;
  887:     default:
  888:       return;
  889:       break;
  890:     }
  891:   thread_list_delete (list, thread);
  892:   thread->type = THREAD_UNUSED;
  893:   thread_add_unuse (thread->master, thread);
  894: }
  895: 
  896: /* Delete all events which has argument value arg. */
  897: unsigned int
  898: thread_cancel_event (struct thread_master *m, void *arg)
  899: {
  900:   unsigned int ret = 0;
  901:   struct thread *thread;
  902: 
  903:   thread = m->event.head;
  904:   while (thread)
  905:     {
  906:       struct thread *t;
  907: 
  908:       t = thread;
  909:       thread = t->next;
  910: 
  911:       if (t->arg == arg)
  912:         {
  913:           ret++;
  914:           thread_list_delete (&m->event, t);
  915:           t->type = THREAD_UNUSED;
  916:           thread_add_unuse (m, t);
  917:         }
  918:     }
  919:   return ret;
  920: }
  921: 
  922: static struct timeval *
  923: thread_timer_wait (struct thread_list *tlist, struct timeval *timer_val)
  924: {
  925:   if (!thread_empty (tlist))
  926:     {
  927:       *timer_val = timeval_subtract (tlist->head->u.sands, relative_time);
  928:       return timer_val;
  929:     }
  930:   return NULL;
  931: }
  932: 
  933: static struct thread *
  934: thread_run (struct thread_master *m, struct thread *thread,
  935: 	    struct thread *fetch)
  936: {
  937:   *fetch = *thread;
  938:   thread->type = THREAD_UNUSED;
  939:   thread->funcname = NULL;  /* thread_call will free fetch's copied pointer */
  940:   thread_add_unuse (m, thread);
  941:   return fetch;
  942: }
  943: 
  944: static int
  945: thread_process_fd (struct thread_list *list, fd_set *fdset, fd_set *mfdset)
  946: {
  947:   struct thread *thread;
  948:   struct thread *next;
  949:   int ready = 0;
  950:   
  951:   assert (list);
  952:   
  953:   for (thread = list->head; thread; thread = next)
  954:     {
  955:       next = thread->next;
  956: 
  957:       if (FD_ISSET (THREAD_FD (thread), fdset))
  958:         {
  959:           assert (FD_ISSET (THREAD_FD (thread), mfdset));
  960:           FD_CLR(THREAD_FD (thread), mfdset);
  961:           thread_list_delete (list, thread);
  962:           thread_list_add (&thread->master->ready, thread);
  963:           thread->type = THREAD_READY;
  964:           ready++;
  965:         }
  966:     }
  967:   return ready;
  968: }
  969: 
  970: /* Add all timers that have popped to the ready list. */
  971: static unsigned int
  972: thread_timer_process (struct thread_list *list, struct timeval *timenow)
  973: {
  974:   struct thread *thread;
  975:   unsigned int ready = 0;
  976:   
  977:   for (thread = list->head; thread; thread = thread->next)
  978:     {
  979:       if (timeval_cmp (*timenow, thread->u.sands) < 0)
  980:         return ready;
  981:       thread_list_delete (list, thread);
  982:       thread->type = THREAD_READY;
  983:       thread_list_add (&thread->master->ready, thread);
  984:       ready++;
  985:     }
  986:   return ready;
  987: }
  988: 
  989: /* process a list en masse, e.g. for event thread lists */
  990: static unsigned int
  991: thread_process (struct thread_list *list)
  992: {
  993:   struct thread *thread;
  994:   unsigned int ready = 0;
  995:   
  996:   for (thread = list->head; thread; thread = thread->next)
  997:     {
  998:       thread_list_delete (list, thread);
  999:       thread->type = THREAD_READY;
 1000:       thread_list_add (&thread->master->ready, thread);
 1001:       ready++;
 1002:     }
 1003:   return ready;
 1004: }
 1005: 
 1006: 
 1007: /* Fetch next ready thread. */
 1008: struct thread *
 1009: thread_fetch (struct thread_master *m, struct thread *fetch)
 1010: {
 1011:   struct thread *thread;
 1012:   fd_set readfd;
 1013:   fd_set writefd;
 1014:   fd_set exceptfd;
 1015:   struct timeval timer_val = { .tv_sec = 0, .tv_usec = 0 };
 1016:   struct timeval timer_val_bg;
 1017:   struct timeval *timer_wait = &timer_val;
 1018:   struct timeval *timer_wait_bg;
 1019: 
 1020:   while (1)
 1021:     {
 1022:       int num = 0;
 1023:       
 1024:       /* Signals pre-empt everything */
 1025:       quagga_sigevent_process ();
 1026:        
 1027:       /* Drain the ready queue of already scheduled jobs, before scheduling
 1028:        * more.
 1029:        */
 1030:       if ((thread = thread_trim_head (&m->ready)) != NULL)
 1031:         return thread_run (m, thread, fetch);
 1032:       
 1033:       /* To be fair to all kinds of threads, and avoid starvation, we
 1034:        * need to be careful to consider all thread types for scheduling
 1035:        * in each quanta. I.e. we should not return early from here on.
 1036:        */
 1037:        
 1038:       /* Normal event are the next highest priority.  */
 1039:       thread_process (&m->event);
 1040:       
 1041:       /* Structure copy.  */
 1042:       readfd = m->readfd;
 1043:       writefd = m->writefd;
 1044:       exceptfd = m->exceptfd;
 1045:       
 1046:       /* Calculate select wait timer if nothing else to do */
 1047:       if (m->ready.count == 0)
 1048:         {
 1049:           quagga_get_relative (NULL);
 1050:           timer_wait = thread_timer_wait (&m->timer, &timer_val);
 1051:           timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg);
 1052:           
 1053:           if (timer_wait_bg &&
 1054:               (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
 1055:             timer_wait = timer_wait_bg;
 1056:         }
 1057:       
 1058:       num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
 1059:       
 1060:       /* Signals should get quick treatment */
 1061:       if (num < 0)
 1062:         {
 1063:           if (errno == EINTR)
 1064:             continue; /* signal received - process it */
 1065:           zlog_warn ("select() error: %s", safe_strerror (errno));
 1066:             return NULL;
 1067:         }
 1068: 
 1069:       /* Check foreground timers.  Historically, they have had higher
 1070:          priority than I/O threads, so let's push them onto the ready
 1071: 	 list in front of the I/O threads. */
 1072:       quagga_get_relative (NULL);
 1073:       thread_timer_process (&m->timer, &relative_time);
 1074:       
 1075:       /* Got IO, process it */
 1076:       if (num > 0)
 1077:         {
 1078:           /* Normal priority read thead. */
 1079:           thread_process_fd (&m->read, &readfd, &m->readfd);
 1080:           /* Write thead. */
 1081:           thread_process_fd (&m->write, &writefd, &m->writefd);
 1082:         }
 1083: 
 1084: #if 0
 1085:       /* If any threads were made ready above (I/O or foreground timer),
 1086:          perhaps we should avoid adding background timers to the ready
 1087: 	 list at this time.  If this is code is uncommented, then background
 1088: 	 timer threads will not run unless there is nothing else to do. */
 1089:       if ((thread = thread_trim_head (&m->ready)) != NULL)
 1090:         return thread_run (m, thread, fetch);
 1091: #endif
 1092: 
 1093:       /* Background timer/events, lowest priority */
 1094:       thread_timer_process (&m->background, &relative_time);
 1095:       
 1096:       if ((thread = thread_trim_head (&m->ready)) != NULL)
 1097:         return thread_run (m, thread, fetch);
 1098:     }
 1099: }
 1100: 
 1101: unsigned long
 1102: thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime)
 1103: {
 1104: #ifdef HAVE_RUSAGE
 1105:   /* This is 'user + sys' time.  */
 1106:   *cputime = timeval_elapsed (now->cpu.ru_utime, start->cpu.ru_utime) +
 1107: 	     timeval_elapsed (now->cpu.ru_stime, start->cpu.ru_stime);
 1108: #else
 1109:   *cputime = 0;
 1110: #endif /* HAVE_RUSAGE */
 1111:   return timeval_elapsed (now->real, start->real);
 1112: }
 1113: 
 1114: /* We should aim to yield after THREAD_YIELD_TIME_SLOT milliseconds. 
 1115:    Note: we are using real (wall clock) time for this calculation.
 1116:    It could be argued that CPU time may make more sense in certain
 1117:    contexts.  The things to consider are whether the thread may have
 1118:    blocked (in which case wall time increases, but CPU time does not),
 1119:    or whether the system is heavily loaded with other processes competing
 1120:    for CPU time.  On balance, wall clock time seems to make sense. 
 1121:    Plus it has the added benefit that gettimeofday should be faster
 1122:    than calling getrusage. */
 1123: int
 1124: thread_should_yield (struct thread *thread)
 1125: {
 1126:   quagga_get_relative (NULL);
 1127:   return (timeval_elapsed(relative_time, thread->ru.real) >
 1128:   	  THREAD_YIELD_TIME_SLOT);
 1129: }
 1130: 
 1131: void
 1132: thread_getrusage (RUSAGE_T *r)
 1133: {
 1134:   quagga_get_relative (NULL);
 1135: #ifdef HAVE_RUSAGE
 1136:   getrusage(RUSAGE_SELF, &(r->cpu));
 1137: #endif
 1138:   r->real = relative_time;
 1139: 
 1140: #ifdef HAVE_CLOCK_MONOTONIC
 1141:   /* quagga_get_relative() only updates recent_time if gettimeofday
 1142:    * based, not when using CLOCK_MONOTONIC. As we export recent_time
 1143:    * and guarantee to update it before threads are run...
 1144:    */
 1145:   quagga_gettimeofday(&recent_time);
 1146: #endif /* HAVE_CLOCK_MONOTONIC */
 1147: }
 1148: 
 1149: /* We check thread consumed time. If the system has getrusage, we'll
 1150:    use that to get in-depth stats on the performance of the thread in addition
 1151:    to wall clock time stats from gettimeofday. */
 1152: void
 1153: thread_call (struct thread *thread)
 1154: {
 1155:   unsigned long realtime, cputime;
 1156:   RUSAGE_T ru;
 1157: 
 1158:  /* Cache a pointer to the relevant cpu history thread, if the thread
 1159:   * does not have it yet.
 1160:   *
 1161:   * Callers submitting 'dummy threads' hence must take care that
 1162:   * thread->cpu is NULL
 1163:   */
 1164:   if (!thread->hist)
 1165:     {
 1166:       struct cpu_thread_history tmp;
 1167:       
 1168:       tmp.func = thread->func;
 1169:       tmp.funcname = thread->funcname;
 1170:       
 1171:       thread->hist = hash_get (cpu_record, &tmp, 
 1172:                     (void * (*) (void *))cpu_record_hash_alloc);
 1173:     }
 1174: 
 1175:   GETRUSAGE (&thread->ru);
 1176: 
 1177:   (*thread->func) (thread);
 1178: 
 1179:   GETRUSAGE (&ru);
 1180: 
 1181:   realtime = thread_consumed_time (&ru, &thread->ru, &cputime);
 1182:   thread->hist->real.total += realtime;
 1183:   if (thread->hist->real.max < realtime)
 1184:     thread->hist->real.max = realtime;
 1185: #ifdef HAVE_RUSAGE
 1186:   thread->hist->cpu.total += cputime;
 1187:   if (thread->hist->cpu.max < cputime)
 1188:     thread->hist->cpu.max = cputime;
 1189: #endif
 1190: 
 1191:   ++(thread->hist->total_calls);
 1192:   thread->hist->types |= (1 << thread->add_type);
 1193: 
 1194: #ifdef CONSUMED_TIME_CHECK
 1195:   if (realtime > CONSUMED_TIME_CHECK)
 1196:     {
 1197:       /*
 1198:        * We have a CPU Hog on our hands.
 1199:        * Whinge about it now, so we're aware this is yet another task
 1200:        * to fix.
 1201:        */
 1202:       zlog_warn ("SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
 1203: 		 thread->funcname,
 1204: 		 (unsigned long) thread->func,
 1205: 		 realtime/1000, cputime/1000);
 1206:     }
 1207: #endif /* CONSUMED_TIME_CHECK */
 1208: 
 1209:   XFREE (MTYPE_THREAD_FUNCNAME, thread->funcname);
 1210: }
 1211: 
 1212: /* Execute thread */
 1213: struct thread *
 1214: funcname_thread_execute (struct thread_master *m,
 1215:                 int (*func)(struct thread *), 
 1216:                 void *arg,
 1217:                 int val,
 1218: 		const char* funcname)
 1219: {
 1220:   struct thread dummy; 
 1221: 
 1222:   memset (&dummy, 0, sizeof (struct thread));
 1223: 
 1224:   dummy.type = THREAD_EVENT;
 1225:   dummy.add_type = THREAD_EXECUTE;
 1226:   dummy.master = NULL;
 1227:   dummy.func = func;
 1228:   dummy.arg = arg;
 1229:   dummy.u.val = val;
 1230:   dummy.funcname = strip_funcname (funcname);
 1231:   thread_call (&dummy);
 1232: 
 1233:   XFREE (MTYPE_THREAD_FUNCNAME, dummy.funcname);
 1234: 
 1235:   return NULL;
 1236: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>